I've written a Minesweeper program, but my code for generating the buttons is taking much longer than I'd like. Here is the GUI code:
this.boardPanel.Controls.Clear();
this.boardValues = new int[mode.size.Width, mode.size.Height];
this.boardFound = new bool[mode.size.Width, mode.size.Height];
this.boardButtons = new Button[mode.size.Width, mode.size.Height];
EventHandler click = new EventHandler(btn_Click);
for (int x = 0; x < boardButtons.GetLength(0); x++)
{
for (int y = 0; y < boardButtons.GetLength(1); y++)
{
boardButtons[x, y] = new Button();
boardButtons[x, y].Size = new Size(Minesweeper.BUTTON_LENGTH, Minesweeper.BUTTON_LENGTH);
boardButtons[x, y].Location = new Point(x * Minesweeper.BUTTON_LENGTH, y * Minesweeper.BUTTON_LENGTH);
boardButtons[x, y].Tag = new Point(x, y);
boardButtons[x, y].Click += click;
this.boardPanel.Controls.Add(boardButtons[x, y]);
}
}
this.boardPanel.Size = new Size(mode.size.Width * Minesweeper.BUTTON_LENGTH, mode.size.Height * Minesweeper.BUTTON_LENGTH);
this.Size = new Size(5 + this.boardPanel.Width + 5 + 8, this.tstMain.Height + 5 + this.boardPanel.Height + 5 + this.stsStatus.Height + 30);
As you can see I am creating an EventHandler for a method called btn_Click
, outside of the loop, and assigning it to each button. This method reads the Tag
field of the clicked button to determine which button as pressed.
In an Intermediate game with a board size of 16x16, generating the buttons takes approximately 2-3 seconds. I know WinForm controls aren't known for the best performance, but is there a way I can generate a number of buttons, assign Event handlers and add them to a panel more efficiently?
-
\$\begingroup\$ i think you need suspend and resume layout msdn.microsoft.com/en-us/library/… \$\endgroup\$pm100– pm1002016年07月15日 15:32:02 +00:00Commented Jul 15, 2016 at 15:32
-
\$\begingroup\$ @pm100 I tried adding this.SuspendLayout() at the beginning of my code and this.ResumeLayout() at the end and saw no difference in the time it took to generate the buttons. I tried the same with this.boardPanel.SuspendLayout, ...etc. and got the same result. Thanks for your suggestion. \$\endgroup\$Django– Django2016年07月15日 16:17:12 +00:00Commented Jul 15, 2016 at 16:17
-
\$\begingroup\$ Using Control's isnt the only way to solve your real problem. Did you consider having only one big control and determine which "virtual" control was clicked from the mouse position? You could then just paint on the control directly.. \$\endgroup\$Mattias Åslund– Mattias Åslund2016年07月15日 21:46:31 +00:00Commented Jul 15, 2016 at 21:46
-
\$\begingroup\$ You're definitely doing something ridiculous if it's taking 2-3 seconds. You haven't posted enough code to replicate exactly what you're doing, but I did a quick test of creating buttons to form a 16 x 16 grid in a panel, with a width/height of 30 per button, in a loop similar to yours. Even without suspending layout, it took no more than 200ms. \$\endgroup\$404– 4042016年07月16日 11:56:28 +00:00Commented Jul 16, 2016 at 11:56
-
\$\begingroup\$ Try to create all buttons fist and add them all at once to the panel with AddRange. \$\endgroup\$t3chb0t– t3chb0t2016年07月16日 14:22:07 +00:00Commented Jul 16, 2016 at 14:22
1 Answer 1
You don't really need the
EventHandler
you can just replaceboardButtons[x, y].Click += click;
withboardButtons[x, y].Click += btn_Click;
. The+=
already works with delegates and kinda does that for you.The only time you want to have
this
is when your method parameters have the same names as your class variables it appears that's not case for you, because I don't see any of the variables used without it.
Overall I really don't see what you can improve, you are simply assigning some values to some variables which really cant be speed up. Windows forms isn't really good for many controls at once that's it.