Is this an efficient way? ArrayList<JButton>

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 714 Views - Last Post: 22 June 2013 - 05:46 PM Rate Topic: -----

#1 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 01:38 AM

I have an ArrayList of JButtons for an onscreen keyboard for a hangman game.

I loop through them to match the source of my actionListener and use the text of the button to send the information on.

public void actionPerformed(ActionEvent e) {
	//start screen sources (difficulty select)
	Object o = (Object) e.getSource();
	if(o==easyButton) {
		clearStartMenu();
		game = new Game(0);
		return;
	}
	if(o==mediButton) {
		clearStartMenu();
		game = new Game(1);
		return;
	}
	if(o==hardButton) {
		clearStartMenu();
		game = new Game(2);
		return;
	}
	//main game sources (letter guess)
	for(int i = 0; i < alphaButtons.size(); i++) {
		if(o==alphaButtons.get(i)) {
			alphaButtons.get(i).setEnabled(false);
			alphaButtons.get(i).setBackground(Color.black);
			game.makeGuess(alphaButtons.get(i).getText());
			return;
		}
	}
}


I guess this is really a 2 part question.

Firstly, is it efficient to use an ArrayList for this or should I change strategy?
Secondly, I put the return statements in so that the method would exit as soon as the source was found and action was taken, thinking that if there was no return statement, the action would be performed, but the method would uselessly check everything else anyway. Am I correct in thinking this?

Thanks in advance,
-Fluke

Is This A Good Question/Topic? 0
  • +

Replies To: Is this an efficient way? ArrayList<JButton>

#2 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 03:30 AM

Efficient for the program or the programmer? I think you should focus on writing easily maintainable and reusable code and leave optimization of the program's execution to the compiler - for now.

So, if you're using the addActionListener( this ) construct that we learned first for most or all of the program's components, you're wondering if there are options to avoid the resulting long chain of if statements required to determine which action to take.

You could break the action listeners up into separate classes, each appropriate and optimized for the type of component and type of action to be taken.

Taking the above to the extreme, you could add an anonymous inner class to each component to be that component's 'private' action listener. Some prefer this approach as it encapsulates the component and its action into a small, tight package that you can pick up and use most anywhere. Others, like pbl, dislike them, but I'm not sure why. For a large group of components (like a virtual keyboard) that do nearly the same thing, writing each component's nearly-identical action listener will become tedious, and you'll ask again, "Is there a better way?"

You might then explore other state-aware patterns (my term) like Observer/Observable or Callback. These patterns become aware of changes in an object's state and react appropriately. In your example, the object observed might be the virtual keyboard, and a state change would be a key press.

These are a few options, I think the most common, and once you have these tools in your toolbox, you'll probably decide that all are useful or the right tool in different situations.

Good luck, and keep coding!
Was This Post Helpful? 1
  • +
  • -

#3 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 04:35 AM

I've used anonymous inner classes before, but the Observer interface is a new one on me. Thank you for introducing me to it.
Was This Post Helpful? 0
  • +
  • -

#4 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 06:07 AM

For exploring the new topics, check out the Dick Baldwin tutorials. I found them very useful, and they build nicely from basic concepts to more complex applications.
Was This Post Helpful? 1
  • +
  • -

#5 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 06:20 AM

Having a little trouble grasping the theory behind applying this to 26 similar JButtons though.

Who is the Observable and who is the Observer?
Was This Post Helpful? 0
  • +
  • -

#6 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 08:15 AM

Still trying to get my head around observer/observable in association with my program, but while thinking I came up with the following:

//I've split the previous action listener into two action listeners,
//this one is now dedicated to the onScreenKeyboard.
public void actionPerformed(ActionEvent e) {
   if(e.getSource() instanceof JButton) { //to make cast safe
      JButton btn = (JButton) e.getSource();
      game.makeGuess(btn.getText());
   }
}


Is this code a good way to obtain the information I need, or is it still "newbie code"? :)/>

I can't test this at the moment if it actually works, but in theory, these 3 lines should cater to as many JButtons as I need, right?

Edit: for clarity, game.makeGuess(String s) is the method signature called by the actionPerformed method, and each button's text is set to the alphabetical character which it represents.

This post has been edited by Flukeshot: 22 June 2013 - 08:19 AM

Was This Post Helpful? 0
  • +
  • -

#7 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2816
  • View blog
  • Posts: 11,918
  • Joined: 20-September 08

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 08:54 AM

I would beware of having an 'all-purpose' event handler. These leads to code that's difficult to scale and maintain, as evidenced in the many uses of return, small though the method is. The first three buttons treated in the handler have a distinct purpose. I would be inclined to treat these thus:

easyButton.add(new GameStartButtonHandler(GameLevel.easy)); // Handler is private inner class. GameLevel is an enum



So, the first three would be absent from the handler you posted, leaving only alpha buttons, which means no iteration should be necessary, only

b.setEnabled(false);
b.setBackground(Color.black);
game.makeGuess(b.getText());

Was This Post Helpful? 1
  • +
  • -

#8 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 09:26 AM

I'll keep that in mind. The problem is (or was) that I have 26 buttons that had to be controlled by one listener. I thought at first that was going to be

if(e.getSource() == button_a) game.makeGuess("a");
if(e.getSource() == button_B)/> game.makeGuess("b");
if(e.getSource() == button_c) game.makeGuess("c");
if(e.getSource() == button_d) game.makeGuess("d");
//......and so on


The thought process through my head at that time was "26 if statements run every time I press a button, there must be a better way to type&program this.."

So I designed the loop. That was also a no-go, it's still running up to 26 times if I hit z. I know that since nobody has a 4bit processor it won't really matter if I did do that, but it still bothers me when I know it can be better.

Just like you say, a specific actionListener for the keyboard really made it a lot simpler.

This post has been edited by Flukeshot: 22 June 2013 - 09:27 AM

Was This Post Helpful? 0
  • +
  • -

#9 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2816
  • View blog
  • Posts: 11,918
  • Joined: 20-September 08

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 09:35 AM

What's the button text? Why not this?

game.makeGuess(b.getActionCommand());

Was This Post Helpful? 1
  • +
  • -

#10 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 09:39 AM

button text is literally "a", "b", "c"
Was This Post Helpful? 0
  • +
  • -

#11 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2816
  • View blog
  • Posts: 11,918
  • Joined: 20-September 08

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 10:04 AM

In that case, see above ;)
Was This Post Helpful? 0
  • +
  • -

#12 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 10:33 AM

I'll get on it tomorrow. Thanks :)
Was This Post Helpful? 0
  • +
  • -

#13 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1414
  • View blog
  • Posts: 3,136
  • Joined: 05-April 11

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 11:53 AM

I would take the more memory using route and keep the code suitable for refactoring and type-safe
It is kinda like g00se suggested expect not using action commands
I have never liked the idea of having to cast the source from the ActionEvent
char[] letters = { ... };

for (char letter : letters) {
	JButton button = new JButton(letter.toString());
	button.addActionListener(new AlphaButtonHandler(button, letter));
	add(button);
}

private class AlphaButtonHandler implements ActionListener {
	private JButton alphaButton;
	private char letter;
	
	public AlphaButtonHandler(JButton alphaButton, char letter) {
		this.alphaButton = alphaButton;
		this.letter = letter;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		game.makeGuess(letter);
	}
}


Was This Post Helpful? 2
  • +
  • -

#14 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10785
  • View blog
  • Posts: 40,160
  • Joined: 27-December 08

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 11:56 AM

Not to be pedantic, but you don't need a char[] for the letters if you're using the entire alphabet. Just iterate from 'a'-'z'. :)
Was This Post Helpful? 0
  • +
  • -

#15 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5908
  • View blog
  • Posts: 12,814
  • Joined: 16-October 07

Re: Is this an efficient way? ArrayList<JButton>

Posted 22 June 2013 - 02:12 PM

Note, casting almost anything to Object is a bit of a waste.

I agree with [member name='CasiOo']'s idea. However, if you've going to make a class for JButton, do that:
private void init() {
	for (char letter='A'; letter<='Z'; letter++) {
		add(new AlphaButtonHandler(letter));
	}
}
private class AlphaButtonHandler extends JButton implements ActionListener {
	private final char letter;
	public AlphaButtonHandler(char letter) {
		super("" + letter);
		this.letter = letter;
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		game.makeGuess(letter);
	}
}



Alternately, an anonymous interface instance works well for this:
for (char letter='A'; letter<='Z'; letter++) {
	final char ch = letter;
	JButton button = new JButton("" + letter);
	button.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			game.makeGuess(ch);
		}
	});
	add(button);
}


Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2