How do I manually invoke an Action in swing? - java

For the life of me I cannot seem to find details on Java Swing Actions :'( When I came across them I immediately realised their usefulness. So far it's all been easy to work with. Now I'm stuck with one little thing: How do I run them manually? I mean by code? Note that I am building the GUI using Netbeans (if that makes any difference). I've come as far as:
Application a = Application.getInstance(JPADemoApp.class);
ApplicationContext ctx = a.getContext();
ActionMap am = ctx.getActionMap(JPADemoView.class, this.app);
Action act = am.get("fetchOrders");
( I wrote all on separate lines to simplify debugging )
So now I have a valid reference to the Action. Now how do I run it?

You can simply invoke the action event's method directly:
for(ActionListener a: buttonExample.getActionListeners()) {
a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
//Nothing need go here, the actionPerformed method (with the
//above arguments) will trigger the respective listener
});
}

If you want to run your action manually, you can generate an ActionEvent and pass it into the actionPerformed method that your Action must implement, as the Action interface extends ActionListener.

Because an Action is an EventListener, you may want to consider implementing an EventListenerList as a way to expose methods that fire actions.

Related

actionCommand in Swing Action seems to be dependent of I18N

Here on Stack Overflow I read a lot about using Swing Actions rather than ActionListeners, so I started to use them within the application's menu.
Everything worked out nice until I introduces I18N, only to find out that the actionCommand of the MenuItem changes accordingly to the language.
Here is what I do:
class ExitAction extends AbstractAction {
public void init() {
putValue(Action.NAME, messageSource.getMessage("app.gui.action.exitApplication"));
}
}
My guess is, that I did understand something wrong and this is not the way to do what I want to do.
Can you please help me?
Two things...
Firstly, NAME affects the text of button, but if not specified, will also set the actionCommand. Property. Instead I think you're after the ACTION_COMMAND_KEY property
Secondly, there should actually be little need for it, as the Action is self contained, hat is, it is it's own ActionListener, so when actionPerformed is called on your Action, you are guaranteed the association

Java: How can I "bundle" GUI elements into groups and listen to multiple groups cleanly?

I am not skilled in GUI design. After much thought, research and experimentation I've developed several design ideas but still none that seems efficient. One design has a Session god object register a listener on every UI element when created, and every object that cares about any action registers a listener on the Session object. This seems simple and robust, as all messaging goes through a central location so it's less likely that anything is lost. It's brute force though, and seems cumbersome and inefficient.
Another design attempts to create subgroups of objects that speak to each other. This avoids the huge top-level Session and seems more efficient, but also seems error prone.
I'm trying to implement a framework for reuse where I group buttons with related purposes into toolbars and have a hierarchical approach to listening for actions performed by toolbars with relevant operations to the listener. I've gotten to this so far:
public class EditorToolBar extends JToolBar {
public static enum Command {
ZOOMIN,
ZOOMOUT,
FINER,
COARSER,
RESET
}
private ButtonCommandListener listener = new ButtonCommandListener();
public EditorToolBar() {
super("Editor Commands");
JButton button;
for (final Command cmd : Command.values()) {
button = new JButton(cmd.toString());
button.setEnabled(true);
button.setToolTipText(cmd.toString() + " Command");
button.setActionCommand(cmd.toString());
button.addActionListener(listener);
add(button);
}
}
public void addActionListener(ActionListener pNewListener) {
listener.cActionNotifier.addListener(pNewListener);
}
private class ButtonCommandListener implements ActionListener {
private NotifierImp<ActionListener> cActionNotifier = new NotifierImp<ActionListener>();
public void actionPerformed(ActionEvent pEvent) {
for (ActionListener listener : cActionNotifier) {
listener.actionPerformed(pEvent);
}
}
}
} // class EditorTooBar
and the listeners implement something like this:
public void actionPerformed(ActionEvent pEvent) {
switch (EditorToolBar.Command.valueOf(pEvent.getActionCommand())) {
case ZOOMIN:
// do something
break;
case ZOOMOUT:
// do something
break;
case FINER:
// do something
break;
case COARSER:
// do something
break;
case RESET:
// do something
break;
default:
System.out.println("Unknown EditorToolBar Command: "+pEvent.getActionCommand());
return;
}
I can enhance the instructor for the enum to also include tooltip text, images, etc. I'd like to reuse this design with just a different enum describing other toolbars. Listeners will distinguish different button actions using ActionEvent.getActionCommand() and use Command.toValue(String). I'd like this to extend to a hierarchy of classes that are listening: a superclass may implement a listener for one type of toolbar, and subclass add to that by listening for a different toolbar type. If the event is not from the toolbar the subclass is interested in, it can forward the event to the superclass. To make this work, I need a way to distinguish between one toolbar and another, but preferably without having to check for every button event possible from that toolbar. Ideally I'd like to have a toolbar factory, and just specifying an enum would be enough to fully describe a toolbar. Not being able to subclass an enum adds to the challenge here.
Is this a promising design pattern to pursue? I've not seen it anywhere else yet. Is there a better way that I should be using rather than inventing something that is inferior? A link to other options would be welcome.
Edit: Based on the answer from yash ahuja I should clarify that when I mention hierarchy I mean similar to the way that key bindings are handled (i.e. do you have a binding? No, then does your container have a binding? ... until someone consumes the key event) not the actual class hierarchy.
As a way to encapsulate functionality, consider combining JToolBar, discussed in How to Use Tool Bars, with Action, discussed in How to Use Actions. The example cited here exports a single tool bar. In contrast, the StyledEditorKit, illustrated here, exports families of Action subtypes that apply to the current selection of a text component.
The design is pretty good but if you create a hierarchy of Tool bars then, in a situation where a particular button is clicked on particular tool bar the corresponding action performed for that button may not be accurate. Also at times multiple events can be triggered.
Also there are some tool bars for which it is difficult to identify that under which super class they should belong or if they are implementing features from multiple tool bars you need multiple inheritance which Java does not supports.
Possibly a combination of Strategy Pattern and Factory Pattern could solve these issues. Please rethink on this and design your solution, sorry I don't have exact design or source for your question , I have just put my thoughts for your solution.
Regards,
Yash

How interface method and abstract method calling default?

When we implement Listener, Renderer or Editor, inside methods how Java its calling automatically?
Code:
Class A implements ActionListener{
A(){
//bla bla
//bla bla
this.addActionListener(btn);
}
public void actionPerformed(ActionEvent e){**// How actionPerformed method called //automatically if we register button**
}
}
How its calling actionPerformed method automatically after registering button object? We are just passing the btn object into addActionListener(btn). How inside its calling that method?
I checked through netbeans inside addActionListener method*. There is no calling method of actionPerformed method. Also if we register it keeps on working. Is it calling by thread anywhere inside? But i checked source code. nothing is there. How?
Events are dispatched from an EventListenerList, owned by the parent JComponent, using a convention outlined in the API and discussed here. Editors and Renderers are evoked by the owning view component.
Addendum: Can we create interface same as it is? How?
Yes, JFreeChart is a fairly accessible example. Although a chart is not itself a JComponent, it uses the same model for its own events.
In Java, anything which happens upon any windows component is dealt with by the Event Dispatcher Thread:
The event dispatching thread (EDT) is a background thread used in Java
to process events from the Abstract Window Toolkit (AWT) graphical
user interface event queue. These events are primarily update events
that cause user interface components to redraw themselves, or input
events from input devices such as the mouse or keyboard.
Whenever you click or do some event, it is the EDT which kick starts the action listener, which is why doing any Thread.sleep in your action listener will eventually freeze the UI for a period of time.
Since your class implements a given interface, your class will guarantee the EDT that it will have a series of methods which the EDT can use to do whatever it needs.
For more information on the EDT, please take a look at this Oracle document.
It's magic.
Event handling is taken care of for you by the AWT API. These events are then queue and dispatched to the various components (via a serious of steps). Each interested party then handles those requests that are of interest to them before passing them up the food chain till it reaches you.
The question is, should you care?
In some respects yes, but do you care how electricity works or just that you can turn on the light switch?
I'm sure there's better documentation, but you could take a look at http://docs.oracle.com/javase/1.3/docs/guide/awt/designspec/events.html for starters...
Swing calls your ActionListener automatically when the action occurs. The actual method call is located deep inside the source code of Swing.

Requesting user input from outside the GUI code, do I need Events or Action to communicate with the GUI in this case?

I'm writing a 2D polygon and physics editor, one functionality is to set a rotation limit for joints.
To use this functionality, the user clicks and drags a line between the joint points which need to receive the limit.
The logic of determining if the pick is valid happens outside of the GUI code.
If a pick is found, I wanted to pop up a JOptionPane.showInputDialog where the user can input the limit.
Thing is, if I do it directly, the program becomes unresponsive, I figure it's because of threading.
I's there a way to define an event listener the GUI can use that doesn't require an actual GUI component?
I want to send an event that also contains a reference to the target object to that component, then telling it that a valid pick has been made and user input is required, and then send the value back via a method of the target object.
I am very inexperienced with Swing.
My hunch is that I might be able to add an ActionListener to the main window, but I don't know how I could address that listener specifically.
As in, how would I need to define an Action that only gets processed by that particular listener?
If that is actually possible, of course.
So far I have only used listeners to let the GUI talk to the logic, not the other way around...
Edit:
The program becomes unresponsive the movement I call
result = JOptionPane.showInputDialog(this,"Enter Limit.");
That just breaks it. Can't even enter anything into the textbox, nor close it, etc.
I figure it's because it spawns a modal dialog that pauses some thread, and calling it from somewhere in the bowels of non GUI code is just not the thing I should do, but I'm too inexperienced to know another way...
Edit2:
I should add that I can use JOptionPane.showInputDialog without any problems if I spawn it, for example, after clicking a button or choosing a popup menu option.
In fact that's how I rename the items I am working with.
But I assume at that point, the dialog is being spawned inside the GUI thread, or this Event Dispatcher queue thing.
The problem with this though is, that this takes visible, interactive GUI components that fire that event.
What I'd like, however, is some sort of component that would spawn JOptionPane.showInputDialog just like a clicked button or context menu would, but without having to be interacted with by the user, but instead by the code.
I guess I could use invisible buttons and emulate mouseclick events, but that's pretty hacky...
Also, I tried spawning Threads and Runnables which spawned the JOptionPane.showInputDialog, but that didn't help either.
Unless I spawn the JOptionPane from a GUI source, everything stalls, and the dialog won't work.
The publisher will have a public add/remove listener, where the subscriber will add itself or be added via another channel to the EventListenerList in the publisher.
You can create your own listener interface that extends EventListener and a function to shoot an event. Below is an example:
import java.util.EventListener;
public interface MyEventListener extends EventListener {
public void myEventOccurred(MyEvent event);
}
You can then create your custom event class, "MyEvent" in the example above like:
import java.util.EventObject;
public class MyEvent extends EventObject {
// customer fields and methods here
public MyEvent(Object source) //more possible args here {
super(source);
//other things here to do what you want
}
}
Now you can have your subscriber implement MyEventListener and override the myEventOccurred(..) method.
Another approach would be to use the SwingWorker class to execute the logic of determining the pick in a dedicated thread without blocking the GUI dispatch thread, and use its callback method to execute the GUI action (open the input dialog).
See : http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
(This page has a better explanation of concept than I could write.)
It should be possible for your background thread to spawn a dialog with invokeAndWait():
final double[] result = new double[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
result[0] = Double.parseDouble(
JOptionPane.showInputDialog("Enter value:"));
} catch(NumberFormatException e) {
result[0] = -1;
}
}
}
// ... do something with result[0]
Here I made the result an array just so that it can be final (accessible to the anonymous class) and also mutable.

action listeners and event sources in Swing

OK, so if I add an ActionListener to a GUI element, and it's the only element I use that ActionListener with, does it matter which of the following lines (a,b) I use to get the checkbox selected state?
final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent event){
boolean bChecked =
// (a) checkbox.isSelected();
// (b) ((JCheckBox)event.getSource()).isSelected();
model.setPrintDebugOn(bChecked);
}
});
It makes sense to me that if I add the ActionListener object to multiple GUI elements, then I should use (b).
And in (b), is it OK to blindly cast event.getSource() to JCheckBox, since I'm the one who added the action listener, or should I program defensively and do an instanceof check?
note: this question is in the context of event listeners in general; kdgregory has some good points below specifically re: checkboxes which I had neglected to consider.
I'd do neither.
If clicking the checkbox is going to start some action, I'd attach an ItemListener, then just look at the selection state in the ItemEvent.
However, checkboxes don't normally invoke actions, they manage state. So a better approach is to examine all of your checkboxes in response to whatever does kick off the action.
Edit: some commentary about the larger issues that the OP raised.
First, it's important to realize that large parts of Swing represent implementation convenience rather than a coherent behavior model. JCheckBox and JButton have nothing in common other than the fact that clicking within their space is meaningful. However, they both inherit from AbstractButton, which provides implementation details such as the button's label. It also assumes that buttons are "pressed", and that pressing a button will initiate some meaningful behavior (the action). In the case of JCheckbox, however, the button press is not important, the change in state is. That state change is signaled to the ItemListener -- which is also defined on AbstractButton even though state changes are meaningless to other button types (the JavaDoc even says "checkbox").
One of the things that Swing did get right -- if hard to use -- is the idea of that an Action is separate from the control initiating that action. An Action object can be invoked from multiple controls: a menu item, a pushbutton on a dialog, a keystroke, whatever. More important from a design perspective is that it takes you away from the idea of a generic "listener" that tries to figure out what needs to happen. I've seen apps where a single listener receives input from the entire menu system, for example, and then runs through a big if/else chain to figure out which menu item was pressed. Using Actions means you have more classes, but in the long run gives you a more maintainable app.
Finally, from a usability perspective, there's a difference between controls that maintain state, such as JCheckbox and JTextArea, and those that initiate actions, such as JButton and JMenuItem. I have seen a (web) app where clicking on a radio button takes you to a different page. That's bad. Even if you're planning to use listeners internally, to update the state of some model, you should ask yourself why the collection of GUI elements do not in themselves provide you with a model.
For the case where the listener is exclusive (such as an anon listener), I use (a).
If the listener will be reused (eg, this is an instance of ActionListener) I'll write it as:
#Override
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == checkbox) {
boolean bChecked = checkbox.isSelected();
// ...
}
}
If you have several checkboxes and they are processed the same way, then instanceof makes sense.
in (b) to be rigourous, you should indeed do a instanceof check, but it's not that important. I would think both these lines are fine and acceptable, though (b) would be "better code"
Although, what is usually done in an action listener is simply call another method customized to your checkbox. So it would look like something like this:
#Override public void actionPerformed(ActionEvent event) {
//your treatment would be in this method, where it would be acceptable to use (a)
onCheckBoxActionPerformed(event)
}
I'd program with b defensively as it's the best-practice option. But if only you are ever going to use the code then there is no reason why you can't do a. However, imagine how happy you will be with yourself if you come back to it at some future point, change something and find you wrote good code which you can directly reuse...

Categories