I don’t really have any code, it’s just a concept I need some help with. Let’s say I have two textboxes, and if you hit enter in one it does one thing and if you hit enter in the other it does something else. If there’s only one listener for text boxes (correct me if I’m wrong) how do you make each box do something different? Do you have to test which one triggered the event somehow? Thanks.
If they do the same thing to different objects, pass in parameters to the text listeners. If they do completely different things, then just make two different listener classes and attach them to the correct buttons.
JTextField txt1 = new JTextField();
txt1.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
doSomething();
}
});
JTextField txt2 = new JTextField();
txt2.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
doSomethingElse();
}
});
The Event object also has a getSource() method, so you could check for the different textboxes in your listener
So would I use a bunch of if statements to check which textbox (for example) it was? What if I had a lot of textboxes?
I think its easier to add a bunch of “else if” statements than to create a bunch of different listeners.
Correct me if im wrong, but each listener has its own thread and if u have a lot of listeners u have a lot of threads that each check whether stuff happened every step. So its better to have one listener and one thread…
You’re wrong.
All listeners do is associate an object with a particular interface with a particular button. They don’t trigger the creation of a new thread. A single AWT event thread checks for and triggers event callbacks for all event listeners, regardless of how many you have registered. Using a big if-else-if-else chain is ugly, fragile and prone to error.
still, its more efficient to use “else if” statements. Cant argue with that.
No.
If you have one listener instance which contains the code for N different buttons, by having N if-else blocks, its time complexity is O(N) (it needs to execute the if-clauses until it finds the right component). But if you have N listeners for the N buttons, the time complexity for executing an action is only O(1).
And first of all, the code is easier to maintain when there are no long if-else chains. It’s a violation of the single responsibility principle to have one listener handle many different operations.
Listeners in Swing are somehow comparable to a mailbox. When Swing detects input, event, property change or other interactivity it forwards up the EventSource to its child components, known as EventListener’s, which catch the Event and proceed it. If one of the eventListeners states that the event is to be consumed (as a reader would read its mail), then it returns to Swing Dispatcher and tells it has been consumed.
The Swing dispatcher is not to be implemented, but the Listener’s must be implemented to tell HOW TO PROCEED with the event received by the Event dispatcher Thread (EDT).
Then it’s up to the programmer to choose whether if-else or switch or other conditions must be held to state if the event can be consumed. AS A CAUTION, each EventListener MUST EXECUTE QUICKLY TO AVOID DEAD-LOCK of the EDT. THAT’S THE RULE PRIOR TO OTHER. ONES .
Therefore “Single responsibility principle” is something that could patternize your methods and Listener’s. if-else are known to be quicker to execute than switch-case. Either way is ok, but to be honest, my own experience told me to focus the code structure on Threading and not on conditions. Let’s say, try to load a 3D-model with one button.
JButton loadModelButton = new JButton(new AbstractAction("load my model...") { public void actionPerformed(ActionEvent e) {
// the model has its own implementation of loading its contents (pictures, sizes, transforms animations, and so on...)
boolean wait = true; // I want to wait for loading to complete
myModel.load(wait);
}});
This first example is such a typical mistake. Hence, my model will block the EDT until its contents are fully loaded and the method returns. One would say : “Uh ! this is because it cannot break my model STATE rule, otherwise the model will fail to display correctly. Or I have visual artefacts, …”.
That’s thoroughly WRONG because Swing interface is BLOCKED (Thread.State.BLOCKED) by the model load() meth’.
Let’s see the second implementation :
JButton loadModelButton = new JButton(new AbstractAction("load my model...") { public void actionPerformed(ActionEvent e) {
// the model has its own implementation of loading its contents (pictures, sizes, transforms animations, and so on...)
Thread t = new Thread() { public void run() {
boolean wait = true; // I want to wait for loading to complete
myModel.load(wait);
synchronized(modelMonitor) { modelMonitor.notifyAll(); }
}});
t.start();
}});
public void waitForLoading(Object monitor) throws InterruptedException{
synchronized(monitor) {
while(true) {
System.out.print(".");
monitor.wait(10);
} System.out.println();
}
}
This is correct, because Swing EDT IS FREED OF CHARGE after starting the model to load its contents. Another object can be used to monitor the model state while it is loading. No other solution can replace a better Threading with Swing Events Dispatcher. 
So would it be better to make a listener for every object or just one listener for every different type of object? (Say one for buttons, text boxes, etc.)
It’s up to you. If you use Netbeans for example to design a GUI, it generates listeners for every object, just containing a method call to a method of your container. If you have some generic functionality that only needs the pointer of the component (e.g. check all textboxes for valid content), you can create just one listener, that performs the task on all components it is attached to.
As pointed out above, as soon as you have huge if/elseif blocks in your listener, your design is probably wrong, but there is imo nothing to say against handling some special cases using an if here and there in an otherwise generic listener.
From my (limited) personal experience I would have to support the suggestion to place your action code immediately with the object as long as it’s a relatively unique action. I am working on my final for my second Java course and it’s a program to manage students, teachers, classes, classrooms, grades, etc. Very “light” in the details but still fairly complex in everything it’s trying to do. I went the route of setting up four main tabs, one for each resource (student, faculty, etc.) and there are several fields and buttons on each tab.
My original start on this app had me using one central action block and if/else logic. This is what most of the samples in various books and the Sun site do, but I have come to regard that “style” bitterly since they really only have a very limited amount of actions being performed in the sample (often just one or two). As my number of actions grew to double digits and kept going this style started getting overwhelming to view and cumbersome to maintain. I finally pulled out 90% of what was in that block and attached the functionality directly to the button objects, for example. The only thing I’m keeping in that block now are actions that are triggered from multiple places (such as a menu item and buttons that run the same report).
Not only has this proven much easier to view and create, but also having the action code directly with the object means it has been very easy to maintain and extend. For example, during my mock-up process I just created the GUI and put a debug statement with each button so that I could click it and see “Student Save Button Clicked” show up in the log. This let me verify quickly that every component was doing what I wanted it to do and responding to it’s actions correctly. I am now going thru all of those componets one at a time and extending them to perform the actual functionality.