which class in a gui program is prefered to handle events? - java

I have got confused by these lines of code:
public class AL extends Frame implements WindowListener,ActionListener {
Button b;
b = new Button("Click me");
b.addActionListener(this);
...
what I understand is that the frame is set as event handler to "its" button.
Is it acceptable to set event handlers that are themselves part of the gui while separate from the source of event?(I mean maybe a button class should handle its events.)
As I have seen many of the events in codes are handled by the jframe. Is there any special purpose behind it?
previously thanks for your time!

The reason you see such code (I've seen a lot of it too, I admit), is that some programmers, especially those writing AWT and/or Swing code, tend to put tons of GUI logic into a single class. The reasons for this vary, but several common ones are:
They've seen such code in examples while learning
They're reluctant to use anonymous classes, or perhaps there's so much code in the event listener's methods that an anonymous class doesn't seem applicable
They believe it's "easier" to understand the code, if the event handling of all child components is done directly in the parent container's methods
They're afraid to have "too many classes" in the project (I'd like to find whoever started that misconception !)
From my experience, a lot of GUI code looks like that. Is that a good way of programming ? ABSOLUTELY NOT !
Any methodology book you read will tell you the same. Such classes are breaking every possible principle of good design. The most basic example would be SRP (http://en.wikipedia.org/wiki/Single_responsibility_principle).
Moreover, GUI classes that handle events as methods of the class, tend to blow out of proportion, and unfortunately, classes of several thousands of lines of code is something I've seen many times in different projects and companies.
Don't fall into this trap. Keep your classes short, have a different class for each of the inner components, unless it's a regular component with a very simple initialization (in which case it would still be preferable to have a factory class do the initialization).
Keep event handling in anonymous classes when there's very few lines of code in the handler, and in separate classes when there's more than a line or two of code.
In short, GUI code is no different than other OO code, and should adhere to the same principles and methodologies.

Related

Java OOP strategy

I have a project called Visual Data Structures. I have a OOP design like this.
Class VisualDataStructures extends JFrame
Class ControlPanel extends JPanel
Class CodePanel extends JPanel
The Class VisualDataStructures has the main. This class has an instances of Class ControlPanel and CodePanel.
The Class ControlPanel has JMenuItem named "Load" inside a JMenuBar.
The Class CodePanel has a JTextArea.
Question:
I need to have a actionlistener for the JMenuItem named "load" inside the class ControlPanel. When the load is clicked, the user will enter the directory of the file, then the file will be loaded and displayed at the JTextArea of the CodePanel.
Do i need to pass the object CodePanel which is instantiated from the VisualDataStructures to the ControlPanel in order for me to use the object and then modify the value of the JTextArea?
Does anybody know a better approach for this? Thanks.
It's a bit difficult to answer that question without seeing the actual code, but I will still try. Maybe if you could share your code somehow, via Github, Bitbucket, as a Gist or in a Pastebin, I could give a better answer. It then might also be better to do that on CodeReview stackexchange instead of StackOverflow.
In general, I find it a bit suspicious that there are so many extends from GUI parent classes. Usage by extension can be a bit of an anti-pattern. It might lead to seemingly simple code in tiny applications in the first place, but in the long run it tends to obfuscate source code because it encourages a mix of business logic and UI. It's a misunderstanding that extension is the core of OOP. It's not. Polymorphic abstraction in order to decouple and invert key dependencies, that's the core of OOP. Extension is just a nice and convenient goody on top of that, and it's overused.
Speaking of that, you might have heard of MVC - Model View Controller. This is the typical pattern for UIs to keep things separate.
You do not want the ActionListener that reacts on the load action to directly know the CodePanel, for a dependency like that this is too concrete. You want to have an abstraction in-between, like an interface, and refer to that interface instead of CodePanel.
When it comes to ActionListener and similar interfaces, you might be interested in upgrading to Java 8, if you haven't done yet. Interfaces like ActionListener with just one abstract method are implicitly functional interfaces, which means you can use lambdas or method references.
In general, I think it helps a lot of always keeping in mind the following question: what if I replace the UI toolkit with a different one? Even if it's not a use case and would never happen, the decoupling and separation of concerns that you do in order to answer that question lead to more modular, better designs which are easier to understand and maintain. In the end, the question what if I replace the UI toolkit with a different one? leads to a design which follows more of the SOLID principles.
When dealing with ActionListener in Swing, you might want to look at interface Action and abstract class AbstractAction. They offer very interesting capabilities. Used in the right way, they can simplify code a lot.

Organize Code for GUI and ActionListener in Java [duplicate]

This question already has answers here:
Implement an interface and override methods in Java?
(6 answers)
Closed 4 years ago.
I am new to Java and was wondering how I would go about implementing ActionListener code in my project. I am aware of inner classes and the implementation the ActionListener interface, but going down that road makes the code look more messy than it probably should.
Would I write another class ActionCode that implements ActionListener and extends GUI or what road would you suggest and why?
What's your best practice advise on that and where can I find those guidelines?
(The JavaDoc seems to explain the basic implementation of ActionListeners, but doesn't seem to have any model how to organize large/medium projects).
In my opinion, there is no "best" approach. Even the code examples from sun/oracle tutorials use different ways to implement listeners.
From my experience, a good approach is:
Use anonymous implementations: People know this pattern and will quickly recognize it. It helps the reader to understand the code if there is a common way to do things
Have a special method, which only handles the listeners (e.g. private void addListeners()): Again, this helps everyone to recognize it and to know where to search for all the logic
Keep the listeners simple. This means less than 5-10 lines of code. If you need more complex logic, call a method.
Keep the number of listeners small. If you need > 50 listeners, you should probably refactor your view. If you need more than 10, you could think about refactoring.
Beside this general points, there are always exceptions. Like if you have a lot of Components with the same behavior, you could write a generic listener with a switch/case. (Typical example: buttons from a calculator or menu buttons).
Or if you have the same logic for multiple components, you could use a specific class.
And so on.
And just to mention it, because there are some examples in the sun/oracle tutorials: Try to avoid implementing a listener interface with the view class itself. This could be ok if you have only one listener, but it is most of the times awful for multiple events from multiple source with different behavior.
Code style can be a matter of personal taste, but modern literature suggests it's more than that. Let the chapter on Classes in Clean Code show you the way.
Classes Should Be Small!
The first rule of classes is that they should be small. The second rule
of classes is that they should be smaller than that. No, we’re not
going to repeat the exact same text from the Functions chapter. But as
with functions, smaller is the primary rule when it comes to designing
classes. As with functions, our immediate question is always “How
small?” With functions we measured size by counting physical lines.
With classes we use a different measure. We count responsibilities...
The Single Responsibility Principle (SRP) states that a class or
module should have one, and only one, reason to change. This principle
gives us both a definition of responsibility, and a guidelines for
class size. Classes should have one responsibility—one reason to
change...
The problem is that too many of us think that we are done once the
program works. We fail to switch to the other concern of organization
and cleanliness. We move on to the next problem rather than going back
and breaking the overstuffed classes into decoupled units with single
responsibilities. At the same time, many developers fear that a large
number of small, single-purpose classes makes it more difficult to
understand the bigger picture. They are concerned that they must
navigate from class to class in order to figure out how a larger piece
of work gets accomplished. However, a system with many small classes
has no more moving parts than a system with a few large classes. There
is just as much to learn in the system with a few large classes. So
the question is: Do you want your tools organized into toolboxes with
many small drawers each containing well-defined and well-labeled
components? Or do you want a few drawers that you just toss everything
into?
Every sizable system will contain a large amount of logic and
complexity. The primary goal in managing such complexity is to
organize it so that a developer knows where to look to find things and
need only understand the directly affected complexity at any given
time. In contrast, a system with larger, multipurpose classes always
hampers us by insisting we wade through lots of things we don’t need
to know right now. To restate the former points for emphasis: We want
our systems to be composed of many small classes, not a few large
ones. Each small class encapsulates a single responsibility, has a
single reason to change, and collaborates with a few others to achieve
the desired system behaviors.
So, based on these heuristics, Nested Classes break SRP. They should almost never happen. Instead, have your GUI classes include instance members of the ActionListeners they register. Keep the listeners in a separate *.listener package. Use interfaces to make them replaceable (Strategy Pattern) wherever deemed effective.
Java and Swing encourage lots of little objects like Listeners and Actions. It's a lot of boiler-plate, but that's the way Java is. There's little benefit in fighting it.
Creating anonymous listeners inline is fairly painless:
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ok();
}
});
But, you often need to reuse actions, say to assign the same action to a menu and a button. You might put them in your main application window as inner classes:
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class MainWindow extends JFrame {
ZapAction zapAction;
public MainWindow() {
setSize(new Dimension(200,200));
zapAction = new ZapAction();
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Foo");
menu.add(new JMenuItem(zapAction));
menuBar.add(menu);
setJMenuBar(menuBar);
JButton zapButton = new JButton(zapAction);
add(zapButton);
}
public void zap() {
// do some zapping
System.out.println("Zap!");
// maybe we're all done zapping?
zapAction.setEnabled(isZappingPossible());
}
public boolean isZappingPossible() {
// determine if there's zapping to be done
return Math.random() < 0.9;
}
class ZapAction extends AbstractAction {
public ZapAction() {
super("Zap");
putValue(AbstractAction.SHORT_DESCRIPTION, "Zap something");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
putValue(AbstractAction.SMALL_ICON,
new ImageIcon(MainWindow.class.getResource("/icons/zap.png")));
setEnabled(true);
}
public void actionPerformed(ActionEvent e) {
zap();
}
}
}
public class Zap {
public static void main(String[] args) {
MainWindow mainWindow = new MainWindow();
mainWindow.setVisible(true);
}
}
Here, ZapAction is package-private visibility. I put all the UI code in it's own package (say org.myorg.myproject.ui). So, all the UI objects have access to the actions.
In a complex swing app, I've gone as far as to create a UI facade layer, which makes a nice place for the actions and all the code that wires them up to various controls. It also makes a convenient place for external code to interact with the UI, keeping UI code isolated from core application code.

One Listener instace for all components or an instance for each component

Short Question
I want to know if there is any good practice recommendation about write one listener instace for all components or an instance for each component.
Extended Question
I'm developing a java swing application.
In the same form i can have a dozen of components (with no relation between them) that use the same listener class. I write each of my listeners in their own class.
The listeners are used to make some validations over the data introduced on the component.
Should i create an instance of the listener class for each component, or should i use the same instance of the listener for all the components.
I can't find any good practice suggestion about this, except this comment, that does not point to any reference.
For the particular case of ActionListener, encapsulate the desired functionality using Action. The wide use of this class throughout Swing suggest its value. This simple example illustrates a few built-in text component actions; this more elaborate example shows how actions can be shared among menus and toolbars.
The alternative is an ever-growing and hard-to-maintain if-then-else ladder based on the event source.
Addendum: Ah, I misread your question. #Andrew's comment is about classes; your question asks about instances. For the former, a single listener tends to evolve toward a a known anti-pattern; earlier versions of the example cited illustrate the problem. For the latter, use only as many instances as required; I usually catch the most egregious violations in a trip through the profiler.
I think the best solution is the one that makes your code the cleanest possible.
Basically, if having one single instance doesn't complicate the code too much then you could create just one instance and share it across the components. Otherwise, you can have multiple instances.
You should choose one which keeps your code readable and maintainable.
If creating instances makes it simpler go ahead and do it but since the behavior remains the same; I believe single instance should work.
Your idea is really interesting........
Moveover if its Swing....then its already based on MVC architecture......
Model - Business Logic and Data
View - Representation of Output
Controller - On which the action is done.
Now i think its also better to have the Business Logic with its data together, so we can easily associate the logic and its corresponding data.
You can always have an a common listener for common EventSource, like JButton...
You can have 4 JButton, which do different works, now you can have a single ActionListener with switch statements..... quite easy to handle......

Building the GUI from the constructor. [Design Decision]

I am just about done with our exam project, and when looking back at what I coded, I feel I did quite alright. Though, stuff could obviously always be alot better. But maybe that's just me.
I was in charge of coding the GUI, and coupling it with the application logic. When making the GUI I made the decision that I would make a class file for every window (e.g. LoginWnd.java), and actually build the GUI in the constructor. I would initalize everything and set all data inside this constructor.
Then in order to navigate through the application, I would set actionlisteners on the jbutton. For example, in SearchWnd, hitting the "Search" jbutton would create a new object of ResultWnd with some specified parameters.
Now i'm kinda wondering: Was this design decision bad in any way? Are there any design paradigms that I should've been aware of?
Thanks.
Your approach sounds fine overall - as long as it works you've achieved the main goal! So my comments here are more about fine-tuning / broader design aspects.
There's nothing fundamentally wrong with doing GUI construction in the constructor providing that the GUI doesn't subsequently change during program execution. The rationale here is that constructors should be reserved for "one-off" construction activities. So it's probably fine for dialog boxes and suchlike that have a pre-determined layout.
If you have a more dynamic GUI where components are frequently being added and removed throughout program execution, then I'd strongly suggest moving this to a set of methods outside the constructor so that they can be called independently of object construction. The constructor itself can still call these methods if needed to do initial setup, but subsequently you have the ability to call these methods later to add new components, refresh the layout etc.
The good news is that this stuff isn't hard to refactor if you get it wrong - it's usually trivial to pull setup code out of a constructor into separate methods later if needed.
Another thing to be aware of is the oft-repeated mantra "prefer composition to inheritance". That is to say, if you can make your GUI work by assembling existing components rather than inheriting and overriding your design will probably be better/more easy to maintain in the long run. For example, I don't think I've ever subclassed JFrame - it's almost always cleaner to just add JPanels within it that contain all the application-specific components.
Finally, be cautious of coupling your GUI components too closely to your application logic. Swing actually does a pretty good job of encoraging you to separate out your data model from the presentation code (e.g. with ListModel and friends). It's worth studying and understanding that approach. The point is that you should usually build GUI components in a way that is fairly application-agnostic, but give them application specific behaviour by connecting them to the right data model and event handlers etc.
I also initialize my GUI in the constructor, so it can't be bad :) But when it gets too long I extract parts of the code into separate GUI components.

Questions: controlling a Swing GUI from an external class and separating logic from user interface

UPDATE: I'm using Netbeans and Matise and it's possible that it could be Matise causing the problems I describe below.
UPDATE 2: Thanks to those who offered constructive suggestions. After rewriting the code without Matise's help, the answer offered by ignis worked as he described. I'm still not sure how the code the Netbeans code generator interfered.
Though I've been programming in Java for awhile I've never done any GUI programming until now. I would like to control a certain part of my program externally (updating a jTextArea field with output from an external source) without requiring any user action to trigger the display of this output in the jTextArea.
Specifically, I want this output to begin displaying on startup and to start and stop depending on external conditions that have nothing to do with the GUI or what the user is doing. From what I understand so far you can trigger such events through action listeners, but these action listeners assume they are listening for user activity. If I must use action listeners, is there a way to trick the GUI into thinking user interaction has happened or is there a more straightforward way to achieve what I want to do?
Also, I'd really like to know more about best practices for separating GUI code from the application logic. From the docs I've come across, it seems that GUI development demands more of a messy integration of logic and user interface than, say, a web application where one can achieve complete separation. I'd be very interested in any leads in this area.
There is no need to use listeners. GUI objects are just like any other objects in the program, so actually
you can use the listener pattern in any part of the program, even if it is unrelated to the GUI
you can invoke methods of objects of the GUI whenever you want during the program execution, even if you do not attach any listeners to the objects in the GUI.
The main "rule" you must follow is that every method invocation performed on objects of the GUI must be run on the AWT Event Dispatch Thread (yes, that's true for Swing also).
http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
So you must wrap code accessing the GUI objects, into either
javax.swing.SwingUtilities.invokeLater( new Runnable() { ... } )
or
javax.swing.SwingUtilities.invokeAndWait( new Runnable() { ... } )
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingUtilities.html
About "separating GUI code from the application logic": google "MVC" or "model view controller". This is the "standard" way of separating these things. It consists in making the GUI code (the "view") just a "facade" for the contents (the "model"). Another part of the application (the "controller") creates and invokes the model and the view as needed (it "controls" program execution, or it should do that, so it is named "controller"), and connects them with each other.
http://download.oracle.com/javase/tutorial/uiswing/components/model.html
For example, a JFoo class in the javax.swing package, that defines a Swing component, acts as the view for one or more FooModel class or interface defined either under javax.swing or one of its subpackages. You program will be the "controller" which instantiates the view and an implementation of the model properly (which may be one of the default implementations found under those packages I mentioned, or a custom implementation defined among your custom packages in the program).
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/package-summary.html
That's a really good question, IMHO... one I asked a couple of years ago on Sun's Java Forums (now basically defunct, thanx to Oracle, the half-witted pack of febrile fiscal fascists).
On the front of bringing order to kaos that is your typical "first cut" of an GUI, Google for Swing MVC. The first article I read on the topic was JavaWorld's "MVC meets Swing". I got lucky, because it explains the PROBLEMS as well as proposes sane solutions (with examples). Read through it, and google yourself for "extended reading" and hit us with any specific questions arrising from that.
On the "simulated user activity" front you've got nothing to worry about really... you need only observe your external conditions, say you detect that a local-file has been updated (for instance) and in turn "raise" a notification to registered listener(s)... the only difference being that in this case you're implementing both the "talker" and the "listener". Swings Listener interface may be re-used for the messaging (or not, at your distretion). Nothing tricky here.
"Raising" an "event" is totally straight forward. Basically you'd just invoke the "EventHappened" method on each of the listeners which is currently registered. The only tricky bit is dealing with "multithreaded-ness" innate to all non-trivial Swing apps... otherwise they'd run like three-legged-dogs, coz the EDT (google it) is constantly off doing everything, instead of just painting and message brokering (i.e. what it was designed for). (As said earlier by Ignis) The SwingUtilies class exposes a couple of handy invoke methods for "raising events" on the EDT.
There's nothing really special about Swing apps... Swing just has a pretty steep learning curve, that's all, especially multithreading... a topic which I had previously avoided like the plague, as "too complicated for a humble brain like mine". Needless to say that turned out to be a baseless fear. Even an old idiot like myself can understand it... it just takes longer, that's all.
Cheers. Keith.
This doesn't exactly answer your question, but you might be interested in using Netbeans for Java GUI development. You can use GUI in Netbeans to do Java GUI development.
Here's a good place to get started -
http://netbeans.org/kb/trails/matisse.html

Categories