I am building a simple POS for my business. I own a little restaurant and would like to make my life easier. I have a class (main menu) that extends JPanel, this class has layout BorderLayout. The menu has a set of panel (NORTH) with button, a JList(WEST), another panel with buttons(CENTER) to change the submenus(EAST), and another buttons(SOUTH) for removing and/or modifying items on list.
When I click on modify (a button on the south panel) another panel should appear. This panel is for the most part the same as the main menu. It has a menu on the north, a list on the west, etc. The part that differs is the actions the buttons on the north and the buttons on the south perform.
My question is:
1) should I create a general class and extend to create this two menus I need
2) should I add an inner class to each extended class for the corresponding functionality of the buttons or should I create external actions.
I am always confused about how to treat events. Create external classes and pass listeners to classes or to use nested classes (but sometimes I find too many nested classes).
If you need me to post the code let me know. Is a little long, this is why I did not post it!
Much of this is opinion based, but here goes anyway...
I would suggest creating subclasses for the different menus, each extending a abstract class defining the common elements. Have them in the same package.
As for event handlers, that's trickier. Sometimes an even handler is only used in one place, in that case, an anonymous inner class (or lambda in Java 8) is the best approach. But if the same handler may be used for different events, then remember the DRY principle, and use a separate class.
Related
I read that the window that appears using the JFrame class is a Container with the predefined features (minimize, closing), but I found people who were not using the JFrame class but other classes (one of them the Container) which was far more hard.
Why do they do it that way? Is it because the JFrame class always has a predefined window that you can manipulate some aspects of it but the Container and the other classes give you more freedom of how you can create a window?
For an example to my question (I don't know if its real or not) in the JFrame class the close button always go to right to corner of the window but if I do it the other way you can put it everywhere you like. (If it can be answered with a yes or no).
So my qusetion is why they do it that way
There are two "main" reasons why. First is about overall good programming.
We tend to recommend avoiding extending from classes to which we are not adding any new functionality or repeatable features. If the whole reason for extending from JFrame is just so you can display some components, then it's really not a good choice or starting point.
JFrame is also a complex, compound component. That is, it's actually made up of a number of other layered components which work together to provide an overall experience.
*From How to Use Root Panes
This means that there is a lot of added complexity you'd have to be willing to manage if you extended from this class, a lot of overhead just to display a few components.
In principle, it's better to use composition over inheritance, which leads into the second point.
Extending from any class locks you into that classes use case. In the case of JFrame, you can only ever display what ever is managed by the class via a JFrame, there is no flexibility or entry point for re-usablility.
If, instead, you started with a base class of, say JPanel, you can add that to what ever container you want when ever you want, it increases the flexibility and re-usability of the class over all.
For an exaple to my question(i dont know if its real or not) in the JFrame class the close button always go to right to corner of the window but if i do it the other way you can put it everywhere you like.(If it can be answered with a yes or no)
Yes and no. The frame border is defined by the look and feel delegate, so you're not actually starting at the right place to begin with anyway.
Most look and feel delegates delegate the frame border to the native platform, in the case of Windows, yes, the close button is on the right, on Mac it's on the left.
In any case, it's better to support user expectations, placing the close button in an unusual place might make the UI "pretty", but diminishes the user experience - as a general guide line, don't diminish the user experience, no matter how awesome your program or UI, user's won't like you for it - but that is a (very broad) question for another day
I have an application that is a Maths Game for kids. Since I'm in college, I've usually only had a god object for all my past projects but for this applciation I've split my code into multiple classes:
MathsGame.java: main class which initialises components and constructs and controls the UI.
DiffScreen.java: contains methods for use on the difficulty selection screen.
GameScreen.java: contains methods for use on the game screen.
EndGameScreen.java: contains methods for use on the end game screen.
MigJPanel.java: extends JPanel and sets layout to MigLayout and adds a matte border.
Each screen that the 3 XScreen classes control is simply an instance of MigJPanel and screens are switched to using a CardPanel container JPanel.
I'm wondering how I can divide my code to each class so that they are properly abstracted but I'm not entirely sure how to approach this.
Should my 3 screen classes be extending from my MigJPanel so these then can be instantiated?
So instead of having my DiffScreen, GameScreen, and EndGameScreen classes solely containing methods related to each screen which are then called from MathsGame, each screen will control itself within its own class.
If yes to the previous question, should the UI components for each screen be made inside that screen's class?
At the moment, all components for each of the three screens are created in my MathsGame constructor. This makes the connection between a screen and the class which 'controls' (I use this word very lightly at the moment) it even further apart. So each screen is just an instance of MigJPanel whose components are constructed in MathsGame. The only relation the EndGameScreen class—for example—has to the End Game screen is that when the MathsGame causes the End Game Screen to be displayed, anything done there makes a method in EndGameScreen be called from MathsGame.
I hope I explained myself well. If not, leave a comment and I'll clarify. Any help would be greatly appreciated!
Yes
Yes.
Focus on self containment and maintain areas of responsibility. It is the responsibility of each UI screen to manage it's content, no one else, in fact, you should guard against allowing unrestricted modification to these components and provide access only through managed methods indirectly (setters and getters), which allow the modification of the properties you want to be changed, and not simply providing the component via a getter, this prevents problems with people removing components you don't want removed, for example.
You could also use interfaces to maintain common functionality if required, so if the MathsGame really only wants to deal with a certain amount of the information/functionality, you can use an interface that all the other screens use which will simplify the process, as the MathsGame only needs to know about the class that implement the interface and not EVERY thing else that might be going on...as a suggestion..
Also, where should I put the code for switching between screens?
From my perspective, it's the responsibility of the MathsGame game to determine when and to which screen should be shown. What I would normally do, is provide some kind of notification process that the current screen can ask the MathsGame to switch screens, maybe via a listener or other agreeded interface. This would mean that each screen would need reference to MathsGame.
Instead of passing it (MathsGame) directly, I'd create an interface that MathsGame would implement (say NavigationController), which defined the calls/contract that each sub screen could use (nextScreen/previousScreen) for example.
Take a look at Model-View-Controller for more ideas
I have a GUI with nested panels(tabbed with nested panels and etc). I need to pass domain object to deeply nested panel. I can think of two ways:
Instantiate all gui objects in one place, like frame class. That
would make passing domain objects dead simple, but Frame class will
be huge and hardly maintanable.
Each panel has its own class, where we instantiate and layout its
components. Now its easy to maintain and classes are clean, but how
do I pass down the chain my domain objects? I dont want to chain-pass
them through constructors of panels that shouldn't even know their
existance. And top level panels would have a ton of these objects to
start with.
Niether way seems like a soulution. How do you usually aproach this?
When I put together a Java Swing GUI, I have a data model for each major GUI element. Note that this isn't an MVC pattern. This is more like a local MV pattern. If you want, you can consider GUI element listeners as the "controller".
Each panel has its own class, where we instantiate and layout its
components. Now its easy to maintain and classes are clean, but how
do I pass down the chain my domain objects?
You have the right idea, although you shouldn't have to do much passing.
My JFrame (or JApplet) will have an associated model class of global type fields. An instance of this model class will usually be passed along to the children elements. This is to allow children elements to react properly when a menu option is selected (as an example)
My JPanel(s) will have an associated model class that maintains the state of text or button children elements.
More complicated children elements, like a JList or a JTree, already have an associated data model. I will probably wrap these associated data models into the JPanel model class for convenience.
The children elements will trigger some sort of selection or action listener. Some of these listeners might need access to model classes besides the model class associated with the parent. In this case, you're going to have to pass the instances of your model classes to the listeners.
This is sort of a Chain of Responsibility pattern. What I would do is have something that creates a map with all of your display objects in it and pass it from constructor to constructor. That way every instance can take what it needs from the map without caring what else is there.
I'm looking for a specific functionality. I want to load a class that extends JPanel for instance and show that JPanel on a separate GUI class.
I'm looking for the ability to switch several of these classes out at will. I have an idea for an educational game software and the classes would be the different games.
I do realize that I can instantiate an instance of each class in my GUI class, but I ran into the issue of them not displaying properly when I try to switch between them. repaint() only works on the last class I added to my content pane. Not sure why as the multiple classes I instantiate are present, it just seems to ignore the preceding classes.
How to swap components?
You can either use CardLayout to switch all the component or add/remove them calling
container.revalidate();
container.repaint();
what is the best way to have JFrames, JDialogs, etc that derive from a common parent but differ some, to be able to have the common parts update automatically when the parent does, but also have new components which are still easily modified in a GUI builder.
One approach I have used before is having placeholder JPanels that populate with existing isolated components at runtime, but I suspect that this is not the best way.
Example frame visual inheritence:
Don't use a GUIBuilder unless you creating some sort of prototype or other throw away code.
Have the components that need to update automatically setup as listeners for some sort of change event. Once an update is needed fire of an "Event" to each listener.