Java Forum / GUI / June 2006
Button event
jaap - 28 Jun 2006 23:58 GMT Hello
I'm a real noob with java. I worked for 4 years with php but now I have to use java. I'm looking for a clean way to get an action behind a button/menuitem. I already found the class actionListener. but the method actionpreformed is not very clean if you want to give 20 buttons an action. The way I know is 20 times else if. There must be an better method.
I will try to use my GUI like an interface. It does'nt have to include much code in my opinion. I think it have to be only some field and button delcarations.
thx for your help
greetz Jaap
Brandon McCombs - 29 Jun 2006 00:16 GMT > Hello > [quoted text clipped - 13 lines] > greetz > Jaap There are 2 ways (that I know of and can remember from class) for designing the way your application handles the action events. You can have your JFrame or JPanel (some central "authority") manage all the events which would cause you to need a bunch of "else if" statements or you can have each button be its own action listener which removes the need for a large "if" structure but makes the individual button code a little more messy, IMO.
Brandon
IchBin - 29 Jun 2006 06:05 GMT > Hello > [quoted text clipped - 13 lines] > greetz > Jaap With you program just implement an ActionListener. After this you have to add the required actionPerformed method. Then just check for which buttons were selected. Here is an example code for buttons objects. Naturally this is not a complete program but just info you were asking about
public class MyButtons implements ActionListener { private JButton deleteButton; private JButton reloadButton; private JButton returnButton; private JButton commitButton;
private final String TEXT_DETELE = "Delete"; private final String TEXT_RELOAD = "Reload"; private final String TEXT_RETURN = "Return"; private final String TEXT_COMMIT = "Commit";
private final String _Click = "Click this button to "; private final String _toolTipDelete = this._Click + "Deleteed Se;ected quote from Database"; private final String _toolTipReload = this._Click + "Reload all remaintng dupicate Quotes from Database"; private final String _toolTipReturn = this._Click + "Return Insert Quotes"; private final String _toolTipCommit = this._Click + "Commit all Delete's to Database";
public MyButtons () { deleteButton = buildButton (deleteButton, TEXT_DETELE, KeyEvent.VK_D, _toolTipDelete)); reloadButton = buildButton (reloadButton, TEXT_RELOAD, KeyEvent.VK_R, _toolTipReload)); returnButton = buildButton (returnButton, TEXT_RETURN, KeyEvent.VK_X, _toolTipReturn)); commitButton = buildButton (commitButton, TEXT_COMMIT, KeyEvent.VK_C, _toolTipCommit)); }
private JButton buildButton (JButton jButton, String label, int keyEvent, String toolTip) { jButton = new JButton(label); jButton.setMnemonic (keyEvent); jButton.addActionListener (this); jButton.setActionCommand (label); jButton.setToolTipText (toolTip); return jButton; } public void actionPerformed (ActionEvent e) { if (this.TEXT_RETURN.equals (e.getActionCommand ())) { } else if (this.TEXT_DETELE.equals (e.getActionCommand ())) { } else if (this.TEXT_RELOAD.equals (e.getActionCommand ())) { } else if (this.TEXT_COMMIT.equals (e.getActionCommand ())) { }
} }
Thanks in Advance... IchBin, Pocono Lake, Pa, USA http://weconsultants.phpnet.us __________________________________________________________________________
'If there is one, Knowledge is the "Fountain of Youth"' -William E. Taylor, Regular Guy (1952-)
Ian Wilson - 29 Jun 2006 11:54 GMT >> I'm a real noob with java. I worked for 4 years with php but now I >> have to use java. [quoted text clipped - 72 lines] > } > } It's a bit rude of me, a mere beginner in Java, to offer comments on IchBin's contribution, so please accept my apologies for doing so:
In this specific example, you don't need to prefix the constants "TEXT_RETURN" etc with "this.".
Eclipse also lays out (Ctrl-Shift-F) the if statement more like a case statement, I prefer this layout: public void actionPerformed(ActionEvent e) { if (TEXT_RETURN.equals(e.getActionCommand())) { // do something } else if (TEXT_DELETE.equals(e.getActionCommand())) { // do something } else if (TEXT_RELOAD.equals(e.getActionCommand())) { // do something } else if (TEXT_COMMIT.equals(e.getActionCommand())) { // do something }
I would also add some defensive code: } else { System.out.println("Internal error: command '" + e.getActionCOmmand() + "' unknown!"; // or JOptionPane etc }
Lastly: I feel impelled to insert `String command = e.getActionCommand` at the top of the method and then change all subsequent 'e.getActionCommand()' to 'command'. An old compulsion to avoid 'expensive' subroutine calls from my Fortran IV days. Not that I worry about microseconds nowadays - its just a habit :-)
Just my GBP 0.02 worth.
jaap - 29 Jun 2006 12:31 GMT Ian Wilson schreef:
>>> I'm a real noob with java. I worked for 4 years with php but now I >>> have to use java. [quoted text clipped - 106 lines] > > Just my GBP 0.02 worth. why I shouldn't use the way like java sun sugests? They create classes for each action. You will get lots of classes but that won't be a problem I sugest, am I wrong?
Knute Johnson - 29 Jun 2006 15:58 GMT > Ian Wilson schreef: >>> [quoted text clipped - 113 lines] > for each action. You will get lots of classes but that won't be a > problem I sugest, am I wrong? There is a lot of memory overhead for each internal class. The single ActionListener with the if-else tests is the way to go if you have a lot different events.
For the others:
public void actionPerformed(ActionEvent ae) { String ac = ae.getActionCommand(); if (ac.equals("???")) { } else if(ac.equals("????")) { }
saves a lot of calls to ActionEvent.getActionCommand() that are not necessary.
 Signature Knute Johnson email s/nospam/knute/
Thomas Fritsch - 29 Jun 2006 12:35 GMT > I'm a real noob with java. I worked for 4 years with php but now I have > to use java. [quoted text clipped - 6 lines] > much code in my opinion. I think it have to be only some field and > button delcarations. I personally prefer a design-pattern roughly alongside the article "How to use Action" at <http://java.sun.com/docs/books/tutorial/uiswing/misc/action.html>.
My code typically looks like this:
//--begin example------------------------------------------------- import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class MainFrame extends JFrame { public static void main(String[] args) { JFrame frame = new MainFrame(); frame.pack(); frame.setVisible(true); }
// Actions used by menu items and buttons: private Action openAction = new OpenAction(); private Action saveAction = new SaveAction(); // ...more actions
public MainFrame() { jbInit(); }
private void jbInit() { getContentPane().setLayout(new BorderLayout());
JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); fileMenu.add(openAction); fileMenu.add(saveAction); menuBar.add(fileMenu); // ... more menus and menu-items setJMenuBar(menuBar);
JToolBar toolBar = new JToolBar(); toolBar.add(openAction); toolBar.add(saveAction); // ... more tool-bar buttons getContentPane().add(toolBar, BorderLayout.NORTH);
JPanel panel = new JPanel(); panel.setLayout(new FlowLayout()); panel.add(new JButton(openAction)); panel.add(new JButton(saveAction)); // ... more buttons getContentPane().add(panel, BorderLayout.CENTER); }
class OpenAction extends AbstractAction { public OpenAction() { putValue(Action.NAME, "Open"); putValue(Action.SMALL_ICON, new ImageIcon("open16.gif")); putValue(Action.MNEMONIC_KEY, new Integer('P')); putValue(Action.SHORT_DESCRIPTION, "open file"); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_O, InputEvent.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { System.out.println(this); // ... do something } }
class SaveAction extends AbstractAction { public SaveAction() { putValue(Action.NAME, "Save"); putValue(Action.SMALL_ICON, new ImageIcon("save16.gif")); putValue(Action.MNEMONIC_KEY, new Integer('A')); putValue(Action.SHORT_DESCRIPTION, "save file"); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { System.out.println(this); // ... do something } }
// ...more Action classes } //--end example------------------------------------------------
 Signature Thomas
Steve W. Jackson - 29 Jun 2006 16:15 GMT > > I'm a real noob with java. I worked for 4 years with php but now I have > > to use java. [quoted text clipped - 92 lines] > } > //--end example------------------------------------------------ I hadn't seen that example before, and I like it quite a lot.
I'd like, however, to point out that the API now says that adding an action directly to a menu, toolbar, etc., is no longer the preferred way (as of 1.3). Instead, it suggests creating the component and using setAction. Of course, the API also shows that common Swing components now accept an Action in their constructors (also since 1.3). So it's not clear if the preferred way is to use setAction or to instead use something like "new JMenuItem(openAction)". In either case, I'm going to keep this idea in mind for future use.
= Steve =
 Signature Steve W. Jackson Montgomery, Alabama
Thomas Fritsch - 29 Jun 2006 18:05 GMT Steve W. Jackson schrieb:
>>My code typically looks like this: [...]
>> private Action openAction = new OpenAction(); [...]
>> JMenu fileMenu = new JMenu("File"); >> fileMenu.add(openAction); [...]
>> JToolBar toolBar = new JToolBar(); >> toolBar.add(openAction); [...]
>> class OpenAction extends AbstractAction { >> public OpenAction() { [quoted text clipped - 18 lines] > (as of 1.3). Instead, it suggests creating the component and using > setAction. Of course, the API also shows that common Swing components I read this API note at JMenu#add(Action) and JToolBar#add(Action) and it irritated me, because Sun didn't say what is the advantage of their preferred way.
> now accept an Action in their constructors (also since 1.3). So it's > not clear if the preferred way is to use setAction or to instead use > something like "new JMenuItem(openAction)". In either case, I'm going > to keep this idea in mind for future use. With openAction having a NAME and a SMALL_ICON value, I found no optical or functional difference between /*1*/ menu.add(openAction); and /*2*/ menu.add(new JMenuItem(openAction));
But there is a remarkable optical difference between /*1*/ toolbar.add(openAction); and /*2*/ toolbar.add(new JButton(openAction)); (1) gives a tool-button with icon and without text (--> looking fine). (2) gives a tool-button with icon and with text (--> looking silly). Therefore, unlike Sun, I still prefer (1).
 Signature Thomas
nblloyd@gmail.com - 29 Jun 2006 16:13 GMT You can also write a generic action listener which will invoke a method on an object:
public class GenericActionListener implements ActionListener {
protected Method method; protected Object object;
public GenericActionListener(Object object, String methodName) { this.object = object; try { method = object.getClass().getMethod(methodName, null); } catch (NoSuchMethodException e) { e.printStackTrace(); } }
// this invokes the method public void actionPerformed(ActionEvent e) { try { method.invoke(object, null); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
So, if you have a controller class (say, GUIController), create methods like "save", "open", "close", etc. in it:
public class GUIController { ... public void save() { ... } ... }
Then, for your buttons, simply do this:
// assuming you have a variable for the GUIController called "guiController" // (or you can use "this" if your GUI is itself the controller JButton saveButton = new JButton(...); saveButton.addActionListener(new GenericActionListener(guiController, "save"));
When the button is clicked, the method guiController.save() will be invoked. It's a nice way to keep your code clean, IMO.
You can also extend GenericActionListener to use methods that have arguments. I'm just showing the bare bones.
- Natasha -
> Hello > [quoted text clipped - 13 lines] > greetz > Jaap
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|