Java Event Binding - java

I'm new in windows application development using java. The question is this "How to i bind events to custom class methods?
As fas i have seen i can register listener classes to swing components to handle events. That is OK but i have to implement a class that implements e.g. the ActionListener interface to handle an event and then implement the actionPerformed method. That means ONE class FOR each event i have to handle?
Can't i have ONE class "listening" for events from all components and have each method in this class do the event handling?"
An example:
class MyEventListener { //pseudo code [no constructors, etc]
public void handleSubmitFormBtn(Event e) {
}
//other methods go here handling events from other swing components
}
Note: I am not sure about the method signature but i hope that you get the point.
Conclusion: ONE method to handle events fired from swing components..is it possible? Is the creation of ONE class for each the event the only way? Can't i route event handling to specific methods for a single class?

In swing what you usually do is use an anonymous class to handle your events, like so:
someControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// handle the event
}
});
Although you can basically have one class handling all your events, and register it to all handlers, anonymous classes, as mentioned above, are the correct swing idiom for handling events.
You can find much more info # http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html

You have a few choices, each with their particular benefits/drawbacks.
anonymous inner classes
component.addActionListener(
new ActionListener()
{
public void actionPerformed(final ActionEvent e)
{
outerClassesMethod();
}
});
inner class
class Foo
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
outerClassMethod();
}
}
outer class
public class Foo
implements ActionListener
{
private final OuterClass target;
public Foo(final OuterClass t)
{
target = t;
}
public void actionPerformed(final ActionEvent e)
{
target.targetClassMethod();
}
}
class implements listener
public class OuterClass
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
method();
}
// somewhere else in the code
{
component.addActionListener(this);
}
}
Each way has good and bad to it.
The anonymous inner class will not allow you to do what you are asking, it can only implement one listener.
The other three will all allow you to do what you want (just add , WindowListener to the implements list for exaple). You likely want the inner class or outer class implementing the listener way to do what you want. I suggest that because the listener is likely very highly coupled to your program, and you will need to do a large set of "if" statements to figure out which control was acted on to perform the actual action (you use evt.getSource() to figure out which control was being acted on and then comare it to your instance variables to see which it was).
However, unless you are in memory constrained device, such as an Android phone, you probably should not do one method for all listeners as it can easily lead to very bad code. If memory is an issue, then go for it, but if it isn't you are better of doing one of the following things:
one listener class per control
one listener class per event type for all controls
one listener class per control per event type
I prefer to code the following way, I find it to be the most flexible:
public class Outer
extends JFrame
{
private final JButton buttonA;
private final JButton buttonB;
{
buttonA = new JButton("A");
buttonB = new JButton("B");
}
// do not put these in the constructor unless the Outer class is final
public void init()
{
buttonA.addActionListener(new AListener());
buttonB.addActionListener(new BListener());
}
private void aMethod()
{
}
private void bMethod()
{
}
public void AListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
aMethod();
}
}
public void BListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
bMethod();
}
}
}
I prefer this way because it forces the methods out of the listeners, which means I only have one place to look for the code (not scattered throughout the inner classes). It also means that it is possible that aMethod() and bMethod() can be reused - if the code is in a listener that isn't practical (it is possible, but not worth the effort).
Doing it the above way is also consistent, and I prefer consistency over most things unless there is a good reason not do it. For instance on the Android I do not do that since class creation is expensive (I still have the listener call methods only, but the class itself implements the listeners and I do an if statement).

You can do this by creating a single action listener that then switches based on the input source, so something like:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonA) {
doSomethingForButtonA(e);
} else if (e.getSource() == buttonB) {
doSomethingForButtonB(e);
}
}
But this is not the recommended way to do it for various reasons. Why do you have an issue with creating a listener for every event to be received? It's the Java model for handling UI events, and if anyone else uses your code or you ever use someone else code it's going to be expected.

You can have one class which has listener methods of many events:
class EventHandler implements ActionListener, ..., MouseListener {
// implementation
}

A conceptual Solution would be to implement the OBSERVER PATTERN.

Melasse framework allows to glue UI component with model w/o creating class (even anonymous one), with syntax Binder.bind(/* source, target, options */).
For example not new class is needed to enable an action/button only when some text is present in a textfield: https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value . Same to display/hide informational or error label.
Most UI components are supported, all Java Beans (with property change support) are.

Related

What is better: Key Listener or key Adapter?

I'm coding a game where the player moves around by using the WASD keys. I know that there are two ways to register keyboard input for this situation: by using key listener or key adapter.
However, it hasn't been very clear what the benefits of each are, and there would be no reason for the Java creators to have two classes that do the same thing.
I want to know which would be the better option.
public abstract class KeyAdapter extends Object implements KeyListener
An abstract adapter class for receiving keyboard events. The methods in this class are empty. This class exists as convenience for creating listener objects.
Actually seems that KeyAdapter is a class that implements KeyListener interface thus we cannot talk about which one is better since the implementation and interface are not equal
What you actually can do is just to extend KeyAdapter class and add some additional support for keyboard events depending on what you actually need
Here you can find examples of how to approach this topic
KeyAdapter (abstract class): One need not implement all the methods - just provide the code for required method(s). In case the application extends this class there will not be a chance to extend any other classes.
KeyListener(interface): In case of implementing this interface, one need to implement all the three methods. But, there is a possibility for extending other classes, later.
I want to know which would be the better option.
This depends upon your application design. Some sample scenarios:
public class MyGuiApp extends KeyAdapter implements ActionListener {
// Override any -or- all of the three KeyAdapter class methods as needed
// No possibility of extending any other class
}
public class MyGuiApp implements KeyListener, ActionListener {
// Override all of the three methods of KeyListener
// Can have empty method bodies for the ones not used
// Possibility of extending any other class, later
}
public class MyGuiApp {
// ...
public void buildGui() {
// ...
JButton button = new JButton("Press me");
button.addKeyListener(new MyKeyListener());
// ...
}
// NOTE: Application will need only one of the implementations, in this sample.
// KeyAdapeter -or- KeyListener
private class MyKeyListener extends KeyAdapter {
// NOTE: Only one method is implemented - in this case
#Override public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
// do some ui related action...
}
}
}
private class MyKeyListener implements KeyListener {
// NOTE: Only all methods are reuired to be implemented - in this case
#Override public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
// do some ui related action...
}
}
#Override public void keyReleased(KeyEvent e) {
// No code - as its not used
}
#Override public void keyTyped(KeyEvent e) {
// No code - as its not used
}
}
}
Example code links:
Here is the link to an example (with complete running code) usage of
KeyAdapter: JButton KeyPressed - Nothing
Happens.
Here is a link to Java tutorial on using KeyListener: How to Write
a Key
Listener.
There is ONE small difference:
KeyListener
The compiler will show error
error: <anonymous class$1> is not abstract and does not override abstract method
keyReleased(KeyEvent) in KeyListener
And in IDE You will get
Add UnImplemented Methods
KeyAdapter
You will NOT get any error message
Hence, It is convenient to use KeyAdapter, if you want to override some methods only.

ActionEvent confusion

I'm very new to Java and I'm confused about the ActionEvent class.
I was under the impression that to use a class you had to create a new object for example:
SomeClass aClass = new SomeClass();
But in this piece of code:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
Event.getSource()
// etc...
}
}
How come you don't need to:
ActionEvent event = new ActionEvent();
Event become an instance of the ActionEvent class without having explicitly tell it.
I'm sorry of this is a dumb question, I'm teaching my self Java, and this is thoroughly confusing to me.
ActionEvent is created somewhere, but it's just not being created explicitly by you. Rather, it's being created in the JButton's code (actually the code is in the AbstractButton class, a parent class for JButton) for notifying all ActionListeners that listener are attached to it. You can view the source file to see the details if you desire.
When you use implements in Java, what you are doing is using an interface. Interfaces require certain methods to be implemented in your code and offer a way to ensure new classes that implement a certain interface have methods that can be called.
Thus, in your example:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
event.getSource()
// etc...
}
}
The ActionListener interface is being implemented by theHandler and therefore the method, actionPerformed(ActionEvent event) is required to be implemented by your class. There is no explicit ActionEvent event = new ActionEvent(); being created here because the ActionEvent is actually being passed through as a parameter to actionPerformed and is otherwise being created somewhere else.
Specifically for your example, you can also do the following instead of using the implements keyword on your class:
public class theHandler {
public theHandler() {
JButton button = new JButton();
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do some stuff here
}
});
}
}
It's really quite simple, there is a thing called static methods. These are methods you can use from a class without making objects of them.
Like the Math class and all it's functions fx. a static method could look like this:
public class HiClass {
public static String sayHi() {
return "Hi!";
}
}
You would then use it in some context like this:
System.out.println( HiClass.sayHi() );
This would print out the string the method returns in your console.
You might ask "why wouldnt I just make all my methods in my classes static then?" there are many reasons, main one I can think of is that when you program you always try to restrcit responsibilities to classes that makes sense, so that the code is more manageable and easier to alter as the program grows.
This is not specific to the context your mentioning though, but it seemed to me your real question is how you can use methods without creating an object?
Hope it answers your question?

Syntax of adding an action listener

When I enter the following code:
JButton aButton = new JButton("Button");
aButtin.addActionListener(this);
my IDE (NetBeans) highlights this as a leaking this statement.
Though there never seem to be any negative repercussions from using the statement as such, some docs that I have read indicate that the more proper method is to add the action listener as a new instance of an inner class that implements ActionListener.
What do NetBeans and these docs know that I don't?
What is really meant by a leaking this statement?
Are there negative repercussions that I am unaware of in the use of this in this way?
there are three ways
aButton.addActionListener(this); in the case that class declarations contains implements ActionListener and there is public void actionPerformed(ActionEvent ae) { too
f.i. pseudocode
public class ButtonDemo implements ActionListener{
aButton.addActionListener(this);
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == aButton) {
}
}
}
aButton.addActionListener(new ButtonPress()); is in the case that ActionLIstener is declared as separate class
f.i. pseudocode
public class ButtonDemo {
aButton.addActionListener(new ButtonPress());
}
public class ButtonPress implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
simpler, clear and without side effects (a.m. two ways) is to create inner anonymous listener
f.i. pseudocode
aButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
}
});
If you use this, then in order for this to handle ActionEvents from multiple sources you need to add logic to check the source or command string of the action. This is perfectly reasonable.
If you use other classes, then you can use ActionListeners that are implemented elsewhere, or reuse ones that were designed for a specific common purpose, or define e.g. anonymous inner classes inline which may be convenient in your situation. This is also perfectly reasonable.
Do not think in terms of "advantages" or "disadvantages" -- this is such a common mistake (Is it "bad" to do xyz? Is xyz "good practice"?). You use whatever makes the most sense for your situation and provides the clearest, most maintainable, properly functioning code. Have common sense, be familiar with the language you are working in and the options available, make sane judgments. A language is a way to express an idea, speak (type) clearly.
I guess one disadvantage of using the inner class implementation is that the listener cannot be reused for other buttons , in case, they should have the same listener.
Something like this :
Can you use the same OnClickListener for different buttons?

Java link event to event handler

I'm working on a GUI library for my game, and I'm trying to find a good way to link events from GUI elements (for example a click-event from a button) to a event handler.
Say I have a button called MyButton.
I would use the following code to set it up (incomplete, just for demonstration):
Button MyButton = new Button();
MyButton.SetParent(MyContainer);
MyButton.SetText("Text inside my button!");
MyButton.SetTextColor(Color.BLACK);
Now this code would be called in one of my gamestates, and what I would like to do is something like this:
MyButton.OnClick(MyButtonClickEvent);
public void MyButtonClickEvent(EventArgs event) {
}
The structure of my gamestates and containers and elements are:
GameEngine->GameState->Container->Elements
What would be the closest solution for this? Thanks in advance.
Java does not have methods as first-class functions, i.e., the language does not provide references to a method which you could pass around like you can in other languages. Your best bet for a construction like the one outlined in your question is to use reflection.
import java.lang.NoSuchMethodException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
public class MyButton {
private Object onClickObject;
private Method onClickMethod;
public void OnClick(Object object, String methodName) throws NoSuchMethodException {
OnClick(object, object.getClass().getMethod(methodName));
}
public void OnClick(Object object, Method method) {
this.onClickObject = object;
this.onClickMethod = method;
}
// MyButton calls this method every time the button is clicked, in
// order to inform the external event handler about it
protected void onClick() throws IllegalAccessException, InvocationTargetException {
onClickMethod.invoke(onClickObject);
}
}
But also note that because methods are no first-class citizens, the above is not the canonical way to implement event listeners in Java. Instead, the Java-way would be to define an interface with a callback method, maybe like this:
public interface ButtonListener {
public void OnClick();
}
(This is assuming you don't have to pass any parameters to the event handler. Usually, this cannot be assumed, thus in addition to a ButtonListener, you'd also have a ButtonEvent which encapsulates the parameters and which is passed to the method(s) defined in the interface.)
Then if you write a class that is interested in receiving events whenever a certain button is clicked, that class would have to implement ButtonListener. In turn, the MyButton class would have to provide a method to register listeners:
public MyButton {
protected List<ButtonListener> buttonListeners;
public void addButtonListener(ButtonListener listener) {
...
}
public void removeButtonListener(ButtonListener listener) {
...
}
protected void fireButtonEvent() {
...
}
}
I'm sure you've seen that pattern in the Java standard class library quite a bit, especially in java.awt and javax.swing -- see for instance java.awt.event.ActionListener, which is what AWT uses for button events.

What is the difference between addActionListener(this) and addActionListener(new ActionListener)?

I want to add event handling to buttons- and I noticed that there are two ways to do this.
Implement the ActionListener interface and then append event listeners to the buttons.
Example:
countButton.addActionListener(this);
And the in the ActionPerformed method will run to display the result.
Do not implement the ActionListener interface and instead do this:
countButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
System.out.println("You clicked the button");
}
});
How does the second method work exactly?????!!!
Thanks!
It is not necessary to define a second class for the first approach. You just need to add the
public void actionPerformed(ActionEvent e) method inside your class and do whatever you want there, after you make your class implement ActionListener. You could use a second class if you wanted to, but it is not necessary. The disadvantage is that you need to specify the source of the event with long if statements in order to take the appropriate action if you have more than one JButtons i.e.
The second approach is adding an anonymous inner ActionListener to every component. It is a more Object Oriented approach, since you have a clearer separation of the functionality of your widgets. It is of advantage to define an additional method called inside each actionPerformed, in order to be able to use this freely and refer to the containing class:
countButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doCountButtonAction(e);
// "this" here would refer to the ActionListener (not that useful)
}
});
and implement the method:
private void doCountButtonAction(ActionEvent e) {
// do whatever you need to here
// using "this" here refers to the containing class (i.e. JFrame, JPanel or whatever)
}
Your question is not exactly on listeners as it is on how interfaces work and how you can instantiate a class in Java. Here's some finer points:
Basicaly, what the JButton class offers you is a way to declare a class who's one particular method will be called when an event is triggered on the button, like when it is clicked. If you look at the Javadocs for JButton and ActionListener, you will now how they work:
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/AbstractButton.html#addActionListener(java.awt.event.ActionListener)
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/event/ActionListener.html
What you can do here in the most old fashioned way possible is to create a class that will be triggered when someone clicks your button:
public class MyButtonActionListener implements ActionListener {
actionPerformed(ActionEvent e) {
System.out.println("Aww, you clicked!");
}
}
Now, once that's done, you can make an insance of it and add it as a listener to your button:
JButton button = new JButton("My button");
MyButtonActionListener myActionListener = new MyButtonActionListener ();
button.addActionListener(myActionListener);
On the other hand, in Java you can instantiate a class anonimousy, which means that instead of having a handler to it's instance (like myActionListener in the above code), you just instantiate it on the fly in the place you need it, and you'll have no handler to use it later. That's what's happening in your code: an ActionListener implementation is delcared on the fly as the parameter for the addActionListener method, that on the fly declaration also includes the statement that your anonymous instance is not just any class, but one that implements ActionListener, and such your anonymous declaration needs to give an implementation of the actionPerformed method.
A third option is to have a class that implements ActionListener (and the actionPerformed method), and inside that class, if you create a JButton and you want to pass it as listener an instance of the ecompasing class, you'll use "this" to reffer to that, as in :
public class MyButtonActionListener implements ActionListener {
private JButton button = new JButton();
public void init() {
button.addActionListener(this);
}
public actionPerformed(ActionEvent e) {
System.out.println("u clicked!");
}
}
There's alot of finer points to this discussion (as in how do you reffer to the "this" on a n anonymous class delcared inside an other class, and how do you reffer to the "this" of the encompassing class instance). I recommend that you read a book on the Sun Certified Java Programmer certification, it has a chapter dedicated to this
That just creates an anonymous class that implements the actionPerformed method. This way you don't have to define a new class for every place that you want to handle an event.
It works the same way as the first technique i.e. The method expects an object which implement ActionListener interface. However, both techniques has its own merits and demerits. The first technique allows utilizing single object on the expense of cluttered if/else code because same method will be handling events for multiple buttons. The second technique allows cleaner separation of logic for each button on the expense of creating multiple anonymous objects (for each button).
Either way, to add an ActionListener you need a class that implements the ActionListener interface (which defines a single method, actionPerformed). addActionListener(this) implies that this implements that interface, and any action performed will call this.actionPerformed.
In the second case, what you're doing is creating a new, anonymous, class that implements the ActionListener interface. When countButton is clicked, the actionPerformed method called is the one in the anonymous class.

Categories