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.
Related
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.
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......
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.
So I've been trying to see how I could best structure my code, because I have an intuitive feel that there must be a better way to achieve what I want without passing around a single object to nearly every UI class in the project.
The project I'm working on has a class RhythmWheel that extends JRootPane. The constructor then goes on to create all the components that form a RhythmWheel. For example it creates an instance of ControlPanel (which extends JPanel) and adds it to itself.
However ControlsPanel needs to have a lot of knowelgde of things that are defined in RhythmWheels like the number of wheels that are currently selected. Currently the constructor for ControlsPanel takes a RhythmWheel as an argument, and then keeps a reference to it. It uses this for things ranging for component a JFileChooser should be parented to to, and as an argument to a function that writes the revelant state of the application to an XML file.
It seems wrong to me that I'm passing around a main component across so many classes. I thought about design patterns, and figured that a singleton might be a solution to this. However I have read numerous times that singletons are evil and are an anti-pattern. I guess the MVC pattern might help, but I'm not sure how I'd implement that in Swing. And most recently I came across Dependency Injection as a possible solution.
I'm a little lost as to what I should be doing, or if I should be doing aything at all. If you'd like to glance at the code I'm working on, you can see it at https://github.com/vamega/RhythmWheels so any advice on how to proceed would be great.
if everything needs a reference to RhythmWheel then it sounds like RhythmWheel is awfully complex. maybe you can break RhythmWheel into a collection of components that (hopefully, and likely, since GUI should reflect logical structure) correspond to particular parts of the GUI?
also, why do all the GUI components keep references to the RhythmWheel (or the appropriate sub-component, if you refactor as described above)? i haven't done much spring programming, but i thought the idea was to structure things round an observer pattern. in that case, the gui components should be registering themselves as observers on the wheel components, so that they can update when the wheel changes.
and yes, this is mvc. the wheel components form your model; the gui is your view. what is less clear is what the controller is. i suspect that it is the high-level wheel.
so, in summary:
the wheel is composed of sub-components
the wheel has high-level methods that reflect what you can "do" to it
the wheel's high-level methods are what are called by actions in the view
the wheel's high-level methods make changes to the wheel's sub-components
the wheel's sub-components, when they change, inform the model, which updates
only the input parts of the view need references to the wheel; the display parts are triggered via callbacks registered with the wheel sub-components.
(to answer the original question directly, i don't see anything so bad in passing around a wheel instance, but as i suggest above, it might be better for it to "fragment" into different components as it gets "lower" into the GUI).
I don't see what's wrong with using singletons. A control panel sounds like a prime candidate for a singleton. Why would have you more than one? Same goes for the others. Anything your currently accessing in ControlPanel from RhythmWheel can be exposed through getters and setters.
Unless there's a model/view separation that you would like to decouple or a view that needs to observe model updates, I wouldn't use MVC.
if i have a class gui and a class for the logic, is holding a reference in gui to logic and logic to gui very bad?
As a general rule it is bad to have the "logic" class having knowledge of the "gui" class. The idea behind the separation is the Model/View design pattern (or Model/View/Controller). The view will need a reference to the model. Look really closely at why the model needs a reference to the view. Usually when the model needs to send information to the view event listeners are used (see javax.swing table and list models for an example).
It should be avoided.
In your GUI, you can have a reference to your Domain Logic, but you should not have a reference to your GUI in your domain logic.
Why ?
Because otherwise, you have no advantage of splitting GUI & Domain logic up in separate files. When your Logic has a dependency to your GUI, then you cannot use your Logic with another GUI.
So, you should try to avoid this dependency from your logic to your gui, or, you should make abstraction of it.
I hope i'm making myself clear here. :)
If you can avoid it, you probably should. Otherwise you might get into a lot of problems with circular dependencies later.
Do they really have to know about each other, or could you have a third "control" concept referencing the two?
The GUI probably needs to expose some kind of interface to the logic class, to have the GUI update when the logic class changes something.
The logic should not have direct knowledge of the the GUI implementation, only its interface.
The Observer Pattern is sometimes used for this.