I was reading about the Event Style architecture and came across this
There are different ways to deliver notifications, but the most common
technique uses an indirect method call that is made through a pointer
initialized at runtime.
But when Java does not have pointers how does it deliver the notifications ?
Java's event system is based on the Observer pattern, except in Java Swing, everything is called a "listener" instead of "observer", and typically implements EventListener (as you can tell from the beast at the top of that link).
For example, a component such as a JButton allows you to add listeners to it that care about when something happens with the button. If your listener cares about button clicks, you would add an ActionListener to the button, and JButton adds it to an internal list to be used later (specifically, it uses EventListenerList). When the user clicks the button, the JButton class will "fire" an event to all of the ActionListener implementations that have been registered with it.
This is basically the observer pattern because you have a subject that's being observed (the JButton) and an observer that wants to be notified about the subject's changes or events (the ActionListener).
Java doesn't have pointers, per se, but that doesn't mean that this can't be accomplished. In C++, you would pass a function pointer to the subject, and the subject would just call that function. Since Java doesn't have function pointers, you pass an object that implements a particular interface to the subject, and the subject will call an exact method on the interface. In the example above, this would be the ActionListener.actionPerformed(ActionEvent) method.
Note that this method is also popular among other Java libraries besides Swing because of the absence of mechanisms like function pointers and the prevalence of Java interfaces.
Java Swing uses listeners to deliver notifications about events.
Here's a snippet of code from a Swing class
Font font = model.getActivityFont();
activityTextFontButton = new JButton(getFontText(font));
activityTextFontButton.setFont(font);
activityTextFontButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
JFontChooser fontChooser = new JFontChooser();
fontChooser.setSelectedFont(model.getActivityFont());
int result = fontChooser.showDialog(dialog);
if (result == JFontChooser.OK_OPTION) {
Font font = fontChooser.getSelectedFont();
String text = getFontText(font);
model.setActivityFont(font);
activityTextFontButton.setText(text);
activityTextFontButton.setFont(font);
JButton dummy = new JButton(text);
setButtonSizes(activityTextFontButton,
connectorTextFontButton, dummy);
dialog.validate();
dialog.pack();
}
}
});
When the button is pressed, the JButton class executes the code that's part of the ActionListener. That's because the JButton class has a reference to the ActionListener instance and knows that the method to execute is actionPerformed.
There are other ways in Java to drive events (see the Observer / Observed classes), but listeners are a pretty cool way to deliver notifications about events.
Related
It might be confusing for some to answer this but I will try to put my question in the best way. I am working with jdbc and gui. Basically I want to display (in buttons format) the particular data received from my sql database. I could get the data correctly and put it to my array of buttons as their names. In other words, I have an ArrayList of buttons with different names/texts received from my database. Thus i really need to make an arraylist of buttons since data are dynamically populated. My problem is, I am so confused of how am going to create an actionListener to each button. Everytime each button is clicked, it must show the values associated with its name. I don't know how am i supposed to pass at least the names of the buttons to my actionListener method (or action Event Handler). If you find it confusing, here is the code for my buttons.
todayTaskButton.add(new JButton(taskForToday.get(i)));
todayTaskButton.get(i).setPreferredSize(new Dimension(300,75));
todayTaskButton.get(i).setBackground(Color.GRAY);
todayTaskButton.get(i).setFont(new Font("Century Gothic",Font.PLAIN,30));
todayTaskButton.get(i).setForeground(Color.WHITE);
todayTaskButton.get(i).setFocusable(false);
Thank you so much
You don't need to pass the name of the button to the ActionListener. It is automatically detected. You just need to implement the method actionPerformed(ActionEvent) in you class.
Then add the listener to the button :
todayTaskButton.get(i).addActionListener(this);
In your actionPerformed method, you can do:
JButton b = (JButton) e.getSource();
String text = b.getText();
Honestly there are so many ways you might achieve this, the problem is picking the right one for you...
You could...
Create a anonymous class for each button, each time your create them
todayTaskButton.get(i).addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...
}
});
While this can work, it can make the code really messy, you also still need a way to map the action back to the button in some way, which can be done using the actionCommand property or using the source property if you don't mind iterating through the list of available buttons
You could...
Create a purpose build class which implements ActionListener for each button, which possibly takes some kind of reference to the data
todayTaskButton.get(i).addActionListener(new TodayActionListener(taskForToday.get(i)));
This is a little more focused, as you don't really care about the button, as you have the "today" value for the listener, so all the normally repeated code could be isolated into a single class and you would simply pass in the "variable" element
You could...
Take full advantage of the Action API and make individual, self contained actions for each button...
public class TaskAction extends AbstractAction {
public TodayAction(String task) {
putValue(NAME, task);
}
#Override
public void actionPerformed(ActionEvent e) {
// Specific action for task
}
}
Then you could simply use
todayTaskButton.add(new JButton(new TaskAction(taskForToday.get(i))));
While this is similar to the previous option, the Action is a self contained unit of work and has a number of properties which the JButton can use to configure it self. The Action can also be re-used for JMenuItems and key bindings, making it incredibly flexible
Have a closer look at How to Use Actions for more details
I am doing a small Java project and using MVC graphical user interfaces to write.
In this project I have dozens of button with different function.
Since I am using MVC to write, I won't use anonymous class listener. I would separate the actionlistener class in the Controller class. As I have dozens of button ,that mean I need to create dozens of actionListioner class for it??
If there is any way to simplify the code?
MVC is a structure to make easier to trace projects. It should not be a problem I think. Research please there are lots of information about it. You should use e.getSource(). Try this:
JButton b1;
JButton b2;
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
// Do something...
}
if (e.getSource() == b2) {
// Do something else...
}
}
Please look these:
One action listener, two JButtons
How to add action listener that listens to multiple buttons
http://www.java2s.com/Tutorial/Java/0260__Swing-Event/Useoneinnerclasstohandleeventsfromtwobuttons.htm
This is always a difficult thing for people to get their heads around. Instead of letting the controller worry about the actual buttons, it should be worried about what the view is allowed to do (ie the actions it can perform), which (presumably updates the model).
So, your view would actually handle the buttons events internally, but, instead of changing the state itself, it would notify the controller the a particular state has changed or action has been performed.
This communication would be managed via a series of interface contracts. This means that are particular controller is expecting to control a particular type of of view, but neither care about the actual implementation, so long as the contract between the two is maintained
With this in mind, it then means that your view can do what ever it likes and generate the "events" in anyway it likes, so long as the contract is upheld and you're not exposing parts of your view to other parts of the program which has no reason to reference it
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.
In my college days, I never realized what patterns were there in the Java API.
Now at work I came across Delegation pattern in Objective C n Cocoa on iOS where one screen sets itself as a delegate on coming screen so that that screen can pass some message to that delegate and it can take some action when it comes back to the previous screen.
I realize that I use to do something similar with when I used to pass "this" as as ActionListener [by implementing the interface] to a JButton and it would automatically call actionPerformed implemented by me in this class and thus I could change any instance data in my JFrame class.
So Is ActionListener an example of Delegate If I am correct ?
EDIT: As correctly mentioned below, It is Observer pattern. We dont set ActionListener we add one. Thus there can be many Listeners to that action.
ActionListener is an example of the observer pattern. You register observers (or listeners) on a component that get called when a specific event occurs.
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...