making buttons with a loop

problem with actionListener

Page 1 of 1

8 Replies - 10714 Views - Last Post: 15 November 2009 - 05:47 PM Rate Topic: -----

#1 cero2k  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 14
  • Joined: 12-May 08

making buttons with a loop

Posted 11 November 2009 - 12:48 AM

I'm trying to dynamically add buttons (JButtons) according to the size of an array, which changes size everytime. I doing it with a for loop and is not really problematic. but when adding an action listener or identifying which button got pressed, that is when things don't work so good.

The button is only supposed to have an icon, so I can't even use the title. all buttons are supposed to do the same work, but to different indexes of an array.


for(int i = 0; i < scenarios.length; i++){
		
			Icon err = UIManager.getIcon("OptionPane.errorIcon");
			del = new JButton();
			del.setIcon(err);
			del.setMnemonic(i);
			PanelX.add(del);
			
			del.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					delButtonAction(evt);	   //method to do button work.
				}
			});

}




I'd was trying to do it via Mnemonics, but I can't seem to retrieve the mnemonic back. any idea how I can differentiate a button from another ???

thanks in advance

Is This A Good Question/Topic? 0
  • +

Replies To: making buttons with a loop

#2 DaneAU  Icon User is offline

  • Great::Southern::Land
  • member icon

Reputation: 284
  • View blog
  • Posts: 1,617
  • Joined: 15-May 08

Re: making buttons with a loop

Posted 11 November 2009 - 01:05 AM

create an ArrayList<JButton> buttons; use a loop to instantiate each button and add an action listener to each. This way you can determine which button is being press or whatever, in public void actionPerformed(ActionEvent e) simply check the buttons using the buttons.get( int )

The problem you may have with this approach is that you may find it dificult to define specific actions or functions to call and the order of the buttons is important.


below is just an idea and is not in order etc
ArrayList<JButton> buttons = new ArrayList<JButton>();

// create each by jsut assigning a name based on its index
for ( int i = 0; i < 10; i++ )
{
   buttons.add( new JButton("Button :: " + i ) );
}


then in actionPerformed
public void actionPerformed( ActionEvent e )
{
   if ( e.getSource() == buttons.get( 0 ) )
      // do something
   if ( e.getSource() == buttons.get( 1 ) )
      // do something
   if ( e.getSource() == buttons.get( 2 ) )
      // do something
   if ( e.getSource() == buttons.get( 3 ) )
      // do something
}


As you can see that would become quite larget for something with a lot of buttons.
Was This Post Helpful? 0
  • +
  • -

#3 Atspulgs  Icon User is offline

  • D.I.C Regular

Reputation: 68
  • View blog
  • Posts: 380
  • Joined: 29-July 09

Re: making buttons with a loop

Posted 11 November 2009 - 06:34 AM

I suggest using ActionCommands.

the following code is an example how you can manipulate the String in your advantage.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;

class buttonMaddness
{
	public static void main(String[] args)
	{
		butMaddFrame myFrame = new butMaddFrame();
		myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

class butMaddFrame extends JFrame implements ActionListener
{
	JButton[][] buttons = new JButton[4][10];
	JPanel mPanel = new JPanel();
	JPanel bPanel = new JPanel();
	JPanel cPanel = new JPanel();
	JTextArea scoreKeeper = new JTextArea();
	Container c = getContentPane();
	int[][] intArray = new int[4][10];

	public butMaddFrame()
	{
		butGen();
		score2();
		//cPanel.add(scoreKeeper);
		bPanel.setLayout(new GridLayout(4,10));
		mPanel.setLayout(new BorderLayout());
		mPanel.add(bPanel, BorderLayout.CENTER);
		mPanel.add(cPanel, BorderLayout.SOUTH);
		c.add(mPanel);

		setTitle("ButtonMaddness");
		setSize(1000,400);
		setLocation(200,200);
		setVisible(true);
	}

	private void butGen()
	{
		for(int i=0;i<4;i++)
			for(int j=0;j<10;j++)
			{
				buttons[i][j] = new JButton(String.valueOf(i)+"x"+String.valueOf(j));
				buttons[i][j].setActionCommand("button" +i +"_" +j);
				buttons[i][j].addActionListener(this);
				bPanel.add(buttons[i][j]);
			}
	}

	private void score()
	{
		String string = "";
		for(int i=0;i<4;i++)
		{
			for(int j=0;j<10;j++)
				string += i+"x"+j+" => " +String.valueOf(intArray[i][j]) +"\t";
			string+= "\n";
		}
		scoreKeeper.setText(string);
	}

	private void score2()
	{
		for(int i=0;i<4;i++)
			for(int j=0;j<10;j++)
				buttons[i][j].setText(String.valueOf(intArray[i][j]));
	}

	public void actionPerformed(ActionEvent e)
	{
		if(e.getActionCommand().contains("button"))
		{
			int i = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll("_", "").charAt(0)));
			int j = Integer.parseInt(Character.toString(e.getActionCommand().replaceAll("button","").replaceAll("_", "").charAt(1)));
			intArray[i][j]++;
			System.out.println(e.getActionCommand() +"  " +i +"  " +j);
		}
		score2();
	}
}



Play around with the program and try understanding it. I personally think its one of the best approaches cuz you can attach any information you need to one actionCommand and button or whatever carries it with all the time. Then you just need to be clever and retrieve the wanted information out of the string :D
Was This Post Helpful? 0
  • +
  • -

#4 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10364
  • View blog
  • Posts: 38,392
  • Joined: 27-December 08

Re: making buttons with a loop

Posted 11 November 2009 - 09:21 AM

I like Bbq's solution, though I want to tweak it a little. He's right to use an ArrayList<JButton> if you have a varying number of buttons b/c ArrayList auto-resizes. I also agree with him on using a single actionPerformed() method instead of having an individual ActionListener method for each JButton. However, instead of using 1000 if statements in the actionPerformed() method, use a for-loop to itearte through the ArrayList to run your comparisons. Why write 1000 lines of code when you can write 2, right? :)
Was This Post Helpful? 0
  • +
  • -

#5 cero2k  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 14
  • Joined: 12-May 08

Re: making buttons with a loop

Posted 11 November 2009 - 05:34 PM

thanks on the suggestions, I'm trying them both to see which behaves better with the rest of the system.

I'll let you know if anything comes up and how everything went.
Was This Post Helpful? 0
  • +
  • -

#6 DaneAU  Icon User is offline

  • Great::Southern::Land
  • member icon

Reputation: 284
  • View blog
  • Posts: 1,617
  • Joined: 15-May 08

Re: making buttons with a loop

Posted 14 November 2009 - 06:08 PM

View Postmacosxnerd101, on 11 Nov, 2009 - 08:21 AM, said:

I like Bbq's solution, though I want to tweak it a little. He's right to use an ArrayList<JButton> if you have a varying number of buttons b/c ArrayList auto-resizes. I also agree with him on using a single actionPerformed() method instead of having an individual ActionListener method for each JButton. However, instead of using 1000 if statements in the actionPerformed() method, use a for-loop to itearte through the ArrayList to run your comparisons. Why write 1000 lines of code when you can write 2, right? :)



Indeed that is true, however for clarity its sometimes easier to use if statements especially if each button needs to call a different function.

// Assumes ArrayList<JButton> buttons;
public void actionPerformed(ActionEvent e)
{
   for ( int i = 0; i < buttons.size(); i++)
   {
        if ( e.getSource() == buttons.get(i) )
        {
              // now what ? how to distinguish function calls
              // 
        }
   }
}


Not to sure as i have never implemented this, however would i be right in saying in order to implement it this way you would also need an ArrayList of some kind of function ? an abstract class perhaps with structs containing single functions with the same name that extend this abstract class ?

eg
abstract class Function
{
    public int x;
    public int y;
   
   public Function( int p_x, int p_y )
   {
      x = p_x;
      y = p_y;
   }

}

// then more functions
class Function1 extends Function
{
    public Function1( int p_x, int p_y )
    {
       super(p_x, p_y);
    }
    
    public int doSomething()
    {
          return super.x + super.y;
    }
}

class Function2 extends Function
{

    public Function( int p_x, int p_y )
    {
          super( p_x, p_y );
    }

    public int doSomething()
    {
          return super.x - super.y;
    }
}

class Function3 extends Function
{
    public Function3( int p_x, int p_y )
    {
        super( p_x, p_y )
    }

    public int doSomething()
    {
          return super.x * super.y;
    }
}




Create an ArrayList<Function> funcs = new ArrayList<Function>(); and store instances of classes eg. something like funcs.add(new Function1(2,2) );, funcs.add(new Function2(2,2) ); , funcs.add(new Function3(2,2) );

Then in the for actionPerformed For loop posted above do something like the following
// NOTES
// Assumes ArrayList<JButton> buttons;
// Also Assumes ArrayList<Function> funcs;

public void actionPerformed(ActionEvent e)
{
   for ( int i = 0; i < buttons.size(); i++)
   {
        if ( e.getSource() == buttons.get(i) )
        {  
             // returns a value corresponding to the function pre-index in an Array.
             funcs.get(i).doSomething();     
        }
   }
}


This approach would be that you probably would need to initialize an instance of a class, and for the example above its probably better that it simply use a default constructor and only pass variables via the doSomething( int, int ) member function. I might be a little vague on this with the post, however i am open for suggestions on an easier solution to managing dynamic generation of components and then performing certain functions based on each particular specific object that has an actionPerformed on it. Buttons are just an example of use.

Would this be a way to address the problem ~ i am curious for my own personal knowledge as i have not had to implement something of a dynamic nature to this respect :)

This post has been edited by bbq: 14 November 2009 - 06:11 PM

Was This Post Helpful? 0
  • +
  • -

#7 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10364
  • View blog
  • Posts: 38,392
  • Joined: 27-December 08

Re: making buttons with a loop

Posted 14 November 2009 - 07:36 PM

Parallel arrays are one thing, but I strongly advocate against parallel ArrayLists (or any resizable collection). It gets really messy when managing them (ie., maintaining the proper correspondences) as the number of elements increases. Most likely when the user wants to display a variable number of buttons, each button generally performs a similar enough function. For example, if you are writing a concentration game and have a variable number of buttons (stored in an array) based on the number of unique elems, number of matches required, etc, then you will have a corresponding parallel array most likely. From there, you are just comparing the contents of the parallel array based on the indices of button clicks.

However, if you really want to define a truly unique function for each button, then you would create probably a class of individual methods (or just cram your methods in the same class as the buttons if you don't mind having a crammed class). Or you just define a unique ActionListener for each button using the addActionListener() method.
Was This Post Helpful? 0
  • +
  • -

#8 DaneAU  Icon User is offline

  • Great::Southern::Land
  • member icon

Reputation: 284
  • View blog
  • Posts: 1,617
  • Joined: 15-May 08

Re: making buttons with a loop

Posted 15 November 2009 - 05:30 PM

Ok cool, i understand what you are saying, i might delve into this next weekend and find a nice framework approach to implementing a structure or format for handling these sorts of questions :)

Just something in my example above, you would create and ArrayList<Function> and on initialisation would include / add each possible function and use it in a static way and final way. It also requires buttons be added in a specific order to work in conjunction with the parallel array.

This post has been edited by bbq: 15 November 2009 - 05:32 PM

Was This Post Helpful? 0
  • +
  • -

#9 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10364
  • View blog
  • Posts: 38,392
  • Joined: 27-December 08

Re: making buttons with a loop

Posted 15 November 2009 - 05:47 PM

View Postmacosxnerd101, on 14 Nov, 2009 - 10:36 PM, said:

Parallel arrays are one thing, but I strongly advocate against parallel ArrayLists (or any resizable collection). It gets really messy when managing them (ie., maintaining the proper correspondences) as the number of elements increases.

...However, if you really want to define a truly unique function for each button, then you would create probably a class of individual methods (or just cram your methods in the same class as the buttons if you don't mind having a crammed class)...


So no, I would not use an ArrayList<Function> as you describe. I would never use any resizable collection in parallel with another list, array or collection. It gets very, very messy.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1