So i have a script that creates buttons, and a script that makes these buttons interactable on certain scenarios.
Problem is, in the script that creates the buttons, 2 of the buttons it creates have more child buttons underneath them. With my following code i can easily make those childbuttons interactable whenever i want, but it wont recognize the parents. I realize why (because my list checks for childs) but I have no clue on how to fix this. Make a second list for the parent buttons or? Code is below.
MenuButton[] MenuButtons = _selectionEditMenuPanel.GetComponentsInChildren<MenuButton>(true);
for (int i = 0; i < MenuButtons.Length; i++)
{
if (MenuButtons[i].name == "edit_group" || MenuButtons[i].name == "edit_ungroup")
{
if (_selection.SelectedPageObject.IsGroup())
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<TestButton>().Interactable = true;
if (!((PageObjectGroup)_selection.SelectedPageObject).IsTempGroup)
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_ungroup");
MenuButtons[i].name = "edit_ungroup";
}
else
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_group");
MenuButtons[i].name = "edit_group";
}
}
else
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_group");
MenuButtons[i].name = "edit_group";
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = false;
}
}
if (MenuButtons[i].name == "edit_crop")
{
//Only make crop button interactive when pageobject bitmap is selected
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = _selection.SelectedPageObject is PageObjectBitmap;
}
//TODO Make this work with edit align? It works with other buttons.
if (MenuButtons[i].name == "edit_align")
{
if (!_selection.SelectedPageObject.IsGroup())
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = false;
}
else
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = true;
}
}
It works for everything except the last check, edit_align(this is a button with childs underneath it) I'll post the general setup of the button creating script below, but NOTE: I cant edit that scripts, it's not mine so please don't advise me to edit that.
private static MenuItem _selectionEditMenu = new MenuItem(Resources.Load<Sprite>("Edit_128"))
{ new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Align_Left_1_128"), "edit_align", true, true, null)
{
new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Distribute_Horizontally_128"), "edit_align_distribute_evenly"
new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Uniform_Height_128"), "edit_align_uniform_height"
I can reach the edit_align_Distribute_evenly & the Uniform height, but not the parent above called: edit_align.
NOTE: I left away some syntax etc cause of company names in there. So don't worry about syntax not being correct.
Thanks, every help is highly appreciated.
Related
i have a problem in Unity3d scripts.
I'm trying to make a sort of combination to open a box.
To open this box, i have to insert a combination of 3 buttons correctly.
This 3 buttons(That are simple GameObject, already placed in my scene) have already an animation, when my character collide with one of them, this one will fall down (same animation to other 2).
So, the combination that i want to insert is "the first correct button is "Button n*2", the second correct button is "Button n*1" and the third correct button is "Button n*3"", but i really don't have idea of how i have to do this.
I tried with if statements but if for example the combination is 123-312-123 the animation of the boxes will show up.
I want that only if i do the combination 213 the box is open, than if i go wrong i have to repeat the combination.
Can anyone help me?
Simple way, have a collection of right sequence:
int[] solution = new int[]{2,1,3};
then anytime a button is used, add its value to another collection:
List<int> sequence = new list<int>();
void OnPress(int buttonValue)
{
if(sequence.Contains(buttonValue)){ return; } // Don't add twice
sequence.Add(buttonValue);
if(sequence.Count == solution.Length)
{
if(CompareSequence())
{
// win
}
else
{
sequence.Clear();
}
}
}
bool CompareSequence()
{
// this should not be since we checked before but just to be sure
if(solution.Length != sequence.Count){ return false; }
for(int i = 0; i < solution.Length; i++)
{
if(solution[i] != sequence[i]){ return false; }
}
return true;
}
Each action on button would pass its own value that gets added to the list.
When the list and the solution are same length, they get compared. If they are same, you move to win section, if not, the sequence is cleared and user needs to refill content.
I don't think I asked the question quite well, so here's an explanation. I want to create buttons invisibly when Form1 loads, instead of changing them each individually, is there a way to change all of them with fewer lines of code?
Note: I do not want to change all buttons, only a certain range of them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Visible = true;
button2.Visible = true;
button3.Visible = true;
button4.Visible = true;
button5.Visible = true;
button6.Visible = true;
button7.Visible = true;
}
By that I mean, is it possible to change those buttons visibility to true without writing them out one by one?
button1 - button7.Visible = true;
something like this..
If you're trying to change only a certain range of buttons, assuming they're all simply called button[x] you could create a function like this:
private void toggleButtons(int start, int end, bool trueOrFalse)
{
for(int x=start; x <= end; x++)
{
this.Controls.OfType<Button>().Where(b => b.Name == "button" + x.ToString()).SingleOrDefault().Visible = trueOrFalse;
}
}
Then you can call it like this using (startNo,endNo,true/false for visibility)
toggleButtons(1, 7, false);
You can use the Controls property to get all of the controls on a form. For example:
foreach(var button in this.Controls.OfType<Button>())
{
button.Visible = false;
}
If you want to change visibility of all buttons in the form, you could do so.
foreach(var button in Controls.OfType<Button>())
{
button.Visible = false; // or true, depending what you want to set
}
If you do no want to change visibility of all Buttons in Form and if you need to filter buttons, based on some criteria, you could do so as well.
For example, if you want to filter buttons whose names starts with "specialButton",
foreach(var button in this.Controls.OfType<Button>().Where(x=>x.Name.StartsWith("specialButton")))
{
button.Visible = false;
}
Similarly, you can filter based on other properties as well.
Another option is to enlist the buttons that needs to be changed in a list. For example, if you need to change only button1 and button2 from a form comprising of 10 buttons, you could
var list = new[] { button1, button2 };
foreach (var item in list)
{
item.Visible = false;
}
I've created a Windows Form which looks like this:
My Windows Form
What I want to do is to color one of these numbered buttons by passing its number to the Form constructor. Here is what I've tried to do, but there are no visible changes. Any suggestions?
public SeatSelection(string seatNumber)
{
InitializeComponent();
foreach(Control ctrl in this.tableLayoutPanel1.Controls)
{
if (ctrl.Text == seatNumber)
{
ctrl.BackColor = Color.Red;
}
}
}
The if statement does find true, and the BackColor does change, but the form wont update:
Watch
Sorry folks, my bad. This code was fine. I made a mistake somewhere else. I did not realised that I called the default constructor immediately after calling this one. Missed else keyword in my if statement, so it was
int seatNumber = Convert.ToInt32(txtSeatNumber.Text);
if(seatNumber>=1 && seatNumber<=21)
seats = new SeatSelection(txtSeatNumber.Text);
seats = new SeatSelection();
seats.Show();
Instead of
int seatNumber = Convert.ToInt32(txtSeatNumber.Text);
if(seatNumber>=1 && seatNumber<=21)
seats = new SeatSelection(txtSeatNumber.Text);
else
seats = new SeatSelection();
seats.Show();
I am trying to reproduce the operation of the Control Expander WPF, or as shown in the menu of Outlook, Vertical Web Menu etc., since in WindowsForms this control does not exist. Here I leave the sample code: Menu_Expader.zip link GoogleDrive.
I have managed to do it using the following controls:
Panels
FlowLayoutPanel
1 Time Control
Button Vectors
Labels Vectors ...
This works perfectly, but it happens that to each panel I must establish a
Maximum Size and Minimum Size therefore every time I add an item inside I must modify the size of the panel where I add it, and the item are very close to each other is a bit annoying for the user's vision.
Example this is what I currently have:
EDIT
Code Sample:
// The state of an expanding or collapsing panel.
private enum ExpandState
{
Expanded,
Expanding,
Collapsing,
Collapsed,
}
// The expanding panels' current states.
private ExpandState[] ExpandStates;
// The Panels to expand and collapse.
private Panel[] ExpandPanels;
// The expand/collapse buttons.
private Button[] ExpandButtons;
// Initialize.
private void Form1_Load(object sender, EventArgs e)
{
// Initialize the arrays.
ExpandStates = new ExpandState[]
{
ExpandState.Expanded,
ExpandState.Expanded,
ExpandState.Expanded,
};
ExpandPanels = new Panel[]
{
panModule1,
panModule2,
panModule3,
};
ExpandButtons = new Button[]
{
btnExpand1,
btnExpand2,
btnExpand3,
};
// Set expander button Tag properties to give indexes
// into these arrays and display expanded images.
for (int i = 0; i < ExpandButtons.Length; i++)
{
ExpandButtons[i].Tag = i;
ExpandButtons[i].Image = Properties.Resources.expander_down;
}
}
// Start expanding.
private void btnExpander_Click(object sender, EventArgs e)
{
// Get the button.
Button btn = sender as Button;
int index = (int)btn.Tag;
// Get this panel's current expand
// state and set its new state.
ExpandState old_state = ExpandStates[index];
if ((old_state == ExpandState.Collapsed) ||
(old_state == ExpandState.Collapsing))
{
// Was collapsed/collapsing. Start expanding.
ExpandStates[index] = ExpandState.Expanding;
ExpandButtons[index].Image = Properties.Resources.expander_up;
}
else
{
// Was expanded/expanding. Start collapsing.
ExpandStates[index] = ExpandState.Collapsing;
ExpandButtons[index].Image = Properties.Resources.expander_down;
}
// Make sure the timer is enabled.
tmrExpand.Enabled = true;
}
// The number of pixels expanded per timer Tick.
private const int ExpansionPerTick = 7;
// Expand or collapse any panels that need it.
private void tmrExpand_Tick(object sender, EventArgs e)
{
// Determines whether we need more adjustments.
bool not_done = false;
for (int i = 0; i < ExpandPanels.Length; i++)
{
// See if this panel needs adjustment.
if (ExpandStates[i] == ExpandState.Expanding)
{
// Expand.
Panel pan = ExpandPanels[i];
int new_height = pan.Height + ExpansionPerTick;
if (new_height >= pan.MaximumSize.Height)
{
// This one is done.
new_height = pan.MaximumSize.Height;
}
else
{
// This one is not done.
not_done = true;
}
// Set the new height.
pan.Height = new_height;
}
else if (ExpandStates[i] == ExpandState.Collapsing)
{
// Collapse.
Panel pan = ExpandPanels[i];
int new_height = pan.Height - ExpansionPerTick;
if (new_height <= pan.MinimumSize.Height)
{
// This one is done.
new_height = pan.MinimumSize.Height;
}
else
{
// This one is not done.
not_done = true;
}
// Set the new height.
pan.Height = new_height;
}
}
// If we are done, disable the timer.
tmrExpand.Enabled = not_done;
}
I want to get a result similar to this - Bootstrap Menu Accordion:
Imitate that operation panels expand according to the quantity of item that it contains as long as it does not protrude from the screen, in which case it will show the scroll bar. I know there are software that provide custom controls like DVexpress, DotNetBar Suite among others, but they are Licensed Software I do not want to use it illegally pirate. Can you help me optimize it or create it in another way?
Environment: Visual Studio 2010 & .NET NetFramework 4.
The original question I made it in StackOverFlow in Spanish.
Modulo (Module)
Menu Principal (Main menu)
Mantenimientos (Maintenance)
Procesos (Processes)
Consultas (Queries)
Reportes (Reports)
Note: If someone speaks Spanish and English and can do a better translation, please edit the question. (Excuse the advertising on the image, I recorded the screen with a software trial version).
I need a label which does something different with every click.
private void open_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
builder = new StringBuilder(4);
builder.Append(zahl1.Text);
builder.Append(zahl2.Text);
builder.Append(zahl3.Text);
builder.Append(zahl4.Text);
code = builder.ToString();
}
if( code== setCode)
{
openAndClose.BackColor = Color.DarkGreen;
setNewCode.Visible = true;
}
else
{
}
}
With the first click the BackColor gets green and the visible is true.
And now it should go back in the start position if I click it again.
That means BackColor should be red and the visible should be false.
Can I do this wth a second Eventhandler?
openAndClose.Click += new EventHandler(open_Click);
Thanks
You could simply do the following:
if(code == setCode)
{
openAndClose.BackColor = openAndClose.BackColor == Color.DarkGreen ? Color.Red : Color.DarkGreen;
setNewCode.Visible = !setNewCode.Visible;
}
The first part toggles the color between green and red, and the second part toggles the visibility.
You should be able to get what you want by having a global field which denotes if the label has been clicked before hand or not.
In short, initially set your flag to false, do something like so:
EventHandler()
{
if(!flag)
{
BackColour = Green
Visible = true
}
else
{
BackColour = Red
Visible = false
}
flag = !flag
}
Attaching multiple event handlers will simply invoke multiple event handlers each time.
I think you do not even need a extra boolean or the check. You can just check if visible then hide, if not visible make it appear