Thread: event handler for an array of buttons

  1. #1
    and the Hat of Clumsiness GanglyLamb's Avatar
    Join Date
    Oct 2002
    Location
    between photons and phonons
    Posts
    1,110

    event handler for an array of buttons

    Hey,

    Firts of this isnt a project in C# but in J# ( since that is what we are getting in programming classes at the moment ).

    Anyway most of the things are pretty much the same i guess.

    Im creating a game like Minesweeper, i have set up the whole world ( a 2 d array of chars ), and then ive set up a 2 D array of buttons.

    My problem now is to get an eventHandler that looks at all members of the 2 d array of buttons.

    Here´s the code i have up till now (only the code of Form1 since thats where ill be needing the eventHandler).
    Code:
    package MineSpotter;
    
    import System.Drawing.*;
    import System.Collections.*;
    import System.ComponentModel.*;
    import System.Windows.Forms.*;
    import System.Data.*;
    
    /**
     * Summary description for Form1.
     */
    public class Form1 extends System.Windows.Forms.Form
    {
    	private System.Windows.Forms.TextBox nMines_txt;
    	private System.Windows.Forms.Label label1;
    	/**
    	 * Required designer variable.
    	 */
    	private System.ComponentModel.Container components = null;
    	private System.Windows.Forms.Button reset_btn;
    	private System.Windows.Forms.Label info_txt;
    	
    	private int nMines;
    	private World w;
    	private System.Windows.Forms.Button defaultButton[][] = new Button [World.HEIGHT-2][World.WIDTH-2];
    
    
    	public Form1()
    	{
    		w = new World(nMines);
    		InitializeComponent();
    		initMyButtons();
    	}
    	/**
    	 * Clean up any resources being used.
    	 */
    	protected void Dispose(boolean disposing)
    	{
    		if (disposing)
    		{
    			if (components != null)
    			{
    				components.Dispose();
    			}
    		}
    		super.Dispose(disposing);
    	}
    	#region Windows Form Designer generated code
    	/**
    	 * Required method for Designer support - do not modify
    	 * the contents of this method with the code editor.
    	 */
    	private void InitializeComponent()
    	{
    		this.reset_btn = new System.Windows.Forms.Button();
    		this.nMines_txt = new System.Windows.Forms.TextBox();
    		this.label1 = new System.Windows.Forms.Label();
    		this.info_txt = new System.Windows.Forms.Label();
    		this.SuspendLayout();
    		// 
    		// reset_btn
    		// 
    		this.reset_btn.set_Font(new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((ubyte)(System.Byte)(((ubyte)0)))));
    		this.reset_btn.set_Location(new System.Drawing.Point(352, 288));
    		this.reset_btn.set_Name("reset_btn");
    		this.reset_btn.set_Size(new System.Drawing.Size(128, 24));
    		this.reset_btn.set_TabIndex(0);
    		this.reset_btn.set_Text("Play Again - Reset");
    		this.reset_btn.add_Click( new System.EventHandler(this.reset_btn_Click) );
    		// 
    		// nMines_txt
    		// 
    		this.nMines_txt.set_Location(new System.Drawing.Point(432, 16));
    		this.nMines_txt.set_Name("nMines_txt");
    		this.nMines_txt.set_Size(new System.Drawing.Size(40, 20));
    		this.nMines_txt.set_TabIndex(3);
    		this.nMines_txt.set_Text("");
    		// 
    		// label1
    		// 
    		this.label1.set_Location(new System.Drawing.Point(360, 16));
    		this.label1.set_Name("label1");
    		this.label1.set_Size(new System.Drawing.Size(72, 23));
    		this.label1.set_TabIndex(6);
    		this.label1.set_Text("Total Mines:");
    		// 
    		// info_txt
    		// 
    		this.info_txt.set_Location(new System.Drawing.Point(360, 48));
    		this.info_txt.set_Name("info_txt");
    		this.info_txt.set_Size(new System.Drawing.Size(112, 40));
    		this.info_txt.set_TabIndex(7);
    		// 
    		// Form1
    		// 
    		this.set_AutoScaleBaseSize(new System.Drawing.Size(5, 13));
    		this.set_ClientSize(new System.Drawing.Size(492, 473));
    		this.get_Controls().Add(this.info_txt);
    		this.get_Controls().Add(this.label1);
    		this.get_Controls().Add(this.nMines_txt);
    		this.get_Controls().Add(this.reset_btn);
    		this.set_Name("Form1");
    		this.set_Text("Lamb The Defuser");
    		this.add_Load( new System.EventHandler(this.Form1_Load) );
    		this.ResumeLayout(false);
    
    	}
    	#endregion
    	
    
    	#region My own button creations
    	private void initMyButtons() {
    		//initialise every button
    		for(int y=0;y<World.HEIGHT-2;y++){
    			for(int x=0;x<World.WIDTH-2;x++){
    				this.defaultButton[y][x] = new Button();		
    			}
    		}
    		for(int y=0;y<World.HEIGHT-2;y++){
    			for(int x=0;x<World.WIDTH-2;x++){
    				this.defaultButton[y][x].set_Location(new System.Drawing.Point((20+(20*y)),((20*x)+20)));
    				this.defaultButton[y][x].set_Name(""+y+x);
    				this.defaultButton[y][x].set_Size(new System.Drawing.Size(20, 20));
    				this.defaultButton[y][x].set_TabIndex(1);
    				this.get_Controls().Add(this.defaultButton[y][x]);
    			}
    		}
    		
    	}
    	#endregion
    	
    
    	//oproepen wanneer er op een button is geklikt
    	public void updatePlace(int x,int y) {
    			defaultButton[y][x].set_Text(""+w.wereld[y+1][x+1]);
    	}
    
    	/**
    	 * The main entry point for the application.
    	 */
    	/** @attribute System.STAThread() */
    	public static void main(String[] args) 
    	{
    		Application.Run(new Form1());
    	}
    
    	private void Form1_Load (Object sender, System.EventArgs e) {
    		info_txt.set_Text("Enter a value between 0 and 100.");
    	}
    
    	private void reset_btn_Click (Object sender, System.EventArgs e) {
    		setWorld();
    	}
    
    	private void setWorld() {
    		nMines = Integer.parseInt(nMines_txt.get_Text());
    		if(nMines>=100 || nMines<=0){
    			info_txt.set_Text("Incorrect Value, Enter a value between 0 and 100.");
    		}else{
    			info_txt.set_Text("");
    			w.createWorld(nMines);
    		}
    	}
    }
    Even if you tell me how to do it in C# ill be thankfull ( since afterall this is a C# board and not a J# board ).

    Thanks in advance,

    Ganglylamb

  2. #2
    the hat of redundancy hat nvoigt's Avatar
    Join Date
    Aug 2001
    Location
    Hannover, Germany
    Posts
    3,130
    My problem now is to get an eventHandler that looks at all members of the 2 d array of buttons.
    Not sure if this is what you want, but you could create one event handler function and use it as eventhandler for any/all of your buttons.

    Create an event handler function as normal. When you set all the buttons properties, set the eventhandler as well. The same for all buttons.

    this.defaultButton[x][y].add_Click( new System.EventHandler(this.YOUR_HANDLER_FUNCTION_HER E) );

    The first argument of an event handler is an object that is the source of the event, in this case the Button that was clicked. This way you can differentiate which one was clicked when your handler function is called.
    hth
    -nv

    She was so Blonde, she spent 20 minutes looking at the orange juice can because it said "Concentrate."

    When in doubt, read the FAQ.
    Then ask a smart question.

  3. #3
    and the Hat of Clumsiness GanglyLamb's Avatar
    Join Date
    Oct 2002
    Location
    between photons and phonons
    Posts
    1,110
    Thanks i´ll try it out within a couple of hours when i get back home.


    ::edit::

    I just tried to do what you suggested.

    Heres the code i changed - the myButton region
    Code:
    #region My own button creations
    	private void initMyButtons() {
    		//initialise every button
    		for(int y=0;y<World.HEIGHT-2;y++){
    			for(int x=0;x<World.WIDTH-2;x++){
    				this.defaultButton[y][x] = new Button();		
    			}
    		}
    		for(int y=0;y<World.HEIGHT-2;y++){
    			for(int x=0;x<World.WIDTH-2;x++){
    				this.defaultButton[y][x].set_Location(new System.Drawing.Point((20+(20*y)),((20*x)+20)));
    				this.defaultButton[y][x].set_Name(""+y+x);
    				this.defaultButton[y][x].set_Size(new System.Drawing.Size(20, 20));
    				this.defaultButton[y][x].set_TabIndex(1);
    				this.defaultButton[x][y].add_Click( new System.EventHandler(this.showValue(defaultButton[x][y],y,x)) ); //THE LINE I ADDED
    				this.get_Controls().Add(this.defaultButton[y][x]);
    			}
    		}
    		
    	}
    	#endregion
    Then i have in the same class this handler - or what i think that can go trough as handler....

    Code:
    	//Event handler for the playfield
    	private void showValue(Button defaultButton[][],int y, int x) {
    		defaultButton[y][x].set_Text(""+w.wereld[y+1][x+1]);
    	}
    Visual studio is giving me these compiler errors:

    The argument in the creation of delegate 'System.EventHandler' must name a method.
    This error points to the line I added when creating these buttons, so to this line
    Code:
    this.defaultButton[x][y].add_Click( new System.EventHandler(this.showValue(defaultButton[x][y],y,x)) );
    I googled on msdn library for the explanation on delegates and found this .

    But I dont see how something like that would resolve my problem and if it did how to implement something like that... I´ve never heard of delegates before so im kind of lost right now on how i should handle this.

    I was even thinking about this just some minutes ago.

    Suppose i create my own Class called Mybuttons, that class will only exists of a copy constructor wich will take a default button Object, placed in the visual studio designer method as an argument, then takes y and x as arguments as well....

    Then it´ll copy all the properties - and also the eventHandler that is assigned to the default button which i created in the visual studio designer...

    After that i would easily be able to change the eventHandler that is generated by visual studio for my designer method created button , thereby also changing the event handler for every other button i would create using my Mybuttons class...

    I was wondering wether something like this would work as well and without using delegates...

    I´m just guessing actually since i dont have a clue again ...

    Any adittional information on delegates or a possible way to solve this problem without using these delegates would be appreciated .

    ::edit 2 ::

    Im going to grab a book on C# from someone now, he says it explains delegates etc so i hope to be back in businnes after reading the part about delegates....

    ::edit 3 ::

    I was able to figure things out on a strange way and actually its not really efficient but it does works...

    Code:
    //at the beginnning of the class
    delegate void showValue(Object sender, System.EventArgs e);
    
    //where i give the buttons there property 
    this.defaultButton[x][y].add_Click( new System.EventHandler(this.showValue) );
    
    //Event handler for the playfield buttons
    	private void showValue (Object sender, System.EventArgs e){
    		for(int y=0;y<World.HEIGHT-2;y++){
    			for(int x=0;x<World.WIDTH-2;x++){
    				if(sender.equals(defaultButton[y][x])){ 
    					defaultButton[y][x].set_Text(""+w.wereld[y][x]);
    				}
    			}
    		}
    Is the event handler i am using now

    Greetings,

    Ganglylamb.

    PS: sorry for the bad indentation - it seems everything is alright as long as i dont edit my code while typing it down here in the form to edit my post.
    Last edited by GanglyLamb; 04-11-2005 at 11:46 AM.

  4. #4
    the hat of redundancy hat nvoigt's Avatar
    Join Date
    Aug 2001
    Location
    Hannover, Germany
    Posts
    3,130
    The way you figured out in Edit 3 is indeed the way to go. You could derive your own label/button class that knows it's own coordinates, so you don't have to go through that loop though
    hth
    -nv

    She was so Blonde, she spent 20 minutes looking at the orange juice can because it said "Concentrate."

    When in doubt, read the FAQ.
    Then ask a smart question.

  5. #5
    and the Hat of Clumsiness GanglyLamb's Avatar
    Join Date
    Oct 2002
    Location
    between photons and phonons
    Posts
    1,110
    Quote Originally Posted by nvoigt
    The way you figured out in Edit 3 is indeed the way to go. You could derive your own label/button class that knows it's own coordinates, so you don't have to go through that loop though
    Well i started thinking about that one yesterday and started creating that class since it can still be very usefull in some other projects i have in mind ( since they will also be using a 2d array of buttons in a way ).

    Anyway thanks for the very usefull information you gave me before it really made me realise how i should work it out.

    Greetings,

    Ganglylamb.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. from 2D array to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 17
    Last Post: 03-24-2009, 10:33 AM
  3. 1-D array
    By jack999 in forum C++ Programming
    Replies: 24
    Last Post: 05-12-2006, 07:01 PM
  4. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM
  5. mode of an array
    By Need Help in forum C Programming
    Replies: 15
    Last Post: 09-17-2001, 08:03 AM