Till now, I have developed simple swing applications so there was no need to break the GUI code into diff. classes but as this application is going to be very large, I decided to break the code into diff. classes so as to make the code more manageable.
But before proceeding, I have some doubts in my mind which are as follows:
Brief description of GUI
It will have a main JFrame (MainFrame). On that a JPanel(MainJPanel) is set whose layout is to be CardLayout. It will contain 25 cards (each card is in the form of JPanel which contains its own swing components).
Q1. I have decided to make 25 classes (each for one JPanel card). Is it correct approach?
Q2. If the above answer is correct, then how can I write code of xxxxActionPerformed() methods of buttons which are on those cards (25 cards) as these methods need access to the object of MainJPanel
e.g.
public void buttonActionPerformed(ActionEvent evt) {
java.awt.CardLayout c = (java.awt.CardLayout) mainJPanel.getLayout();
c.show(mainJPanel, "card1"); // card1 is this card
mainJPanel.updateUI();
}
I googled for swing examples but almost all of them shows the use of diff. swing components. Can you also please suggest me a link that shows some swing examples that contain GUI codes in diff. classes.
Q1) That sounds like quite a lot of classes. While it's possible that each class has distinct functionality I find it more likely that you could combine some of those into more common classes. For example instead of YellowCard and BlueCard you could simply have ColorCard where color is a parameter.
Q2) Model View Presenter (MVP) and Model View Controller (MVC) are two (or one, depending on your view) common design patterns which help design GUIs so that everyone has the data they need.
More specifically, you might not need all cards to have a reference to the parent panel. For example, if you have a BurgerPanel which allows the user to order burgers and a StatusPanel which shows how many burgers have been ordered you can communicate between them as follows...
Create a StoreStatus object and pass it to both BurgerPanel and StatusPanel. When the user orders a burger with burger panel it updates the store status. The store status notifies the StatusPanel of this update via the observer pattern and then the StatusPanel reflects the change.
UPDATE: In regards to your specific example you would either some kind of reference to the parent class or you could notify it of updates with the observer patterns. (The advantage of the observer pattern is that any changes to the parent class couldn't create changes in the child classes.)
I would say you are correct in creating a class for each card. This is a logical way to split up the code.
If you need to reference the MainJPanel then simply pass it into the constructor of each card class and keep a reference to it.
Related
I currently have a rather large class that extends JPanel. The class is about 2000 lines of code although it is broken up into many mostly small functions. I want to add a second mode which will render something totally different in the panel. For organization, I am thinking of simply passing the panel to another class and have the other class render the panel. Or I could just add onto the first class. What would be the best approach? The only ugliness with the second approach is that the main class would have to check what mode it is in and if it is in the second mode, it would have to pass mouse and key movements to the secondary class.
If it's something completely different, keep them in two different classes so if anyone else were to look at your code, they'll understand better of what's going on.
I'm currently doing a course in Object Oriented programming in Java, and we need to create a game for our last lab so my lab partner an me chose to make a 2 player chess game without AI and using the model-view-controller approach.
We are a little bit lost as how and where to start so we need a simple UML diagram so we know where to start.
We have come up with the following classes, but aren't sure if they are enough or if all the data fields and methods make sense:
ChessBoard (model) class and ChessLogic class (?)
View class to present data from the model class
Controller class that updates the model data as well as the View class based on user input
An abstract Piece class or interface which is inherited or implemented by each of the 6 pieces.
This diagram is a nice start but there's still a lot to be done. I will draw your attention on some points you need to improve, but without preventing you from learning by doing.
First some formalities:
use the arrows for the relationships only to indicate navigability. If the link is bidirectional, either use 2 arrows or none. For example, here we could understand that View knows ChessBoard, but it is not clear if ChessBoard knows about Views: how can the ChessBoard then inform Views that the state of the board has changed after a move was done ?
indicate the multiplicity: for exemple, I wonder if it is one ChessBoard for one View or could there be several Views for a same Chessboard ?
avoid ambiguity between associations and properties. For example, in View, you have a model property of type ChessBoard. But you also have an association with ChessBoard. So is this all the same ChessBoard ? Or do we have two ChessBoards, one associated and one embedded ? It would be clearer to remove the model from the properties, and indicate model as the name of the asscoiated object at the end of the association.
The association starting from Controller that suddenly splits into two is not very practical, especially if you'll tell us about association ends and multiplicity. Prefer to visually have two very distinct lines .
Now to the core:
Your model should not just be a ChessBoard. The model should be a Game that has a couple of elements. ChessBoard is only one of them: the current position of the Pieces. But what about the layers ? Where are they ? How do I know that it's two of them ? How does the Controller know wo's turn it is ?
By calling something ChessBoard that is more than a chess board, you might create a confusion. For example, can the board know for sure if isGameOver(), just with the information on the position of the pieces ? Isn't it possible that a player decides to abandon ? So try to name your classes according to what they really represent.
How can I find out which Pieces are where on the board ?
How do I know the color of a Piece ?
How can I find out if a board's cell is free or occupied ?
What happens if a Piece is removed from the board because it was taken ?
Your UML diagram must evolve to clarify all this. So I think to complete the ChessBoard and the Piece you're missing at least Game, Player, BoardCell (also called "Square", and perhap's some containers of Pieces still on the board for each player.
Once you've completed, you also need to think about the relation between the Model, the View and the Controler, to be sure that the Controller knows enough to give commands to the model, but also that the model can inform the View when something has changed.
P.S: I've added some links to a the Chess Programming Wiki since this website describes well some elementary concepts for programming the game, some usual questions as well as a lot of references. But be aware however that although very informative this resource is not very object oriented.
I've been tasked with making a GUI that essentially takes a bit of user input and does some folder/file manipulation on various drives accessible by the machine the program is being run on. While designing this GUI, I'm starting to realize that MVC will make my life much easier and anyone else who decides to modify code, but I can't really see how this can be done via NetBeans.
I've done a bit of reading up on this topic, and I can't really see any clear cut answers as to whether or not this can be done on NetBeans. Surely it can be done if I programmatically build the GUI, but that somewhat defeats the purpose of why I chose to use NetBeans.
Netbeans is fine to do this.
The key thing to realize is that while all of the basic Swing components are MVC, for the most part you don't interact with them that way. A simple text field has it internal model, but that model isn't your model, the text field is more a primitive.
Your model deals with higher level events (button actions and what not), rather than button presses and arrow moves and mouse clicks.
So, for high level MVC, the primary mechanism of communication is through PropertyChangeListeners. And the basic task of building your app up is wiring the PCLs of the assorted data elements along with their GUI components together.
For example, a simple case is you have a list of items. And that list is rendered on the screen via a JTable, and that table is on a JPanel.
Your list has it's own model, i.e. it's not simply a Java List. It's not a List because standard Java Lists don't support PCL notifications. But your Model would obviously wrap such a List.
Now, the next question is how do you wire up JTable to be associated with your List model.
One, you could subclass JTable and bind it to your Model. Or, more simply, you use the JTable as a primitive, and let the enclosing JPanel manage the interaction between your Model and the JTable.
That means having your JPanel implement PropertyChangeListener, and then, when wiring everything up, you do something like this:
ListModel myModel = new ListModel();
ListPanel myPanel = new ListPanel();
myModel.addPropertyChangeListener(myPanel);
Now, whenever your ListModel is changed, is will notify the ListPanel.
On your ListPanel you can having something like:
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ListModel.CHANGED)) {
ListModel model = (ListModel) evt.getSource();
DefaultTableModel tm = (DefaultTableModel) listTable.getModel();
tm.setRowCount(0);
for (String s : model.getList()) {
tm.addRow(new Object[]{s});
}
}
}
Now, you can see this simply reloads the entire table model, but you can make your property changes as fine grained as you want. You can also see that if this was some other model (like a Person or something) you can populate individual text fields and whatnot on the panel.
This is a pretty simple GUI, but it shows the fundamentals of how this all wires together. I think a bit of this is lost in the Swing examples which are great for one panel screens but don't scale at all when you start adding other views.
Your JPanels basically become combined VC, as your GUI gains complexity you can factor those kinds of things out, but its works pretty well for reasonable amounts of screens and such.
There are two ways in which Netbeans can help you leverage its codebase: GUI Builder (1) and NB Platform (2).
(1) Netbeans had for a while one of the better drag-n-drop GUI builders in the Java world, codenamed Matisse.
That said, it's been a long time since I worked with it - and I never really liked the generated code, it wasn't very comprehensible (which of course is not the purpose of auto-generated code). For more complex UIs we hand-wrote the layout and the work was bearable, even if not the most pleasant. For simple UIs, I'd try GUI Builder again, for complex UIs with a lot of wired logic, I'd probably still would write it by hand.
To see how the GUI Builder works, take a look at one of the many tutorial videos, e.g. this one:
NetBeans GUI Builder: Adding Components
(2) Netbeans Platform is to Netbeans, what RCP is to Eclipse. A rich set of components developed for an IDE, that can be reused. I briefly looked into NB Platform and we would have used it, if the project didn't change course. Maybe this SO question can shed more light on this aspect: Which Rich Client Platform to use?.
Concerning MVC. There was JSR 296, a generic Swing Application Framework, that looked somewhat promising, but was withdrawn in 2011. That did not stop people to fork it and work on it, as this project shows: Better Swing Application Framework, with a release in mid 2012. Even if you do not use such a framework, please do not put all code in one class (as you mention in you comment), but create a simple model/controller and keep the UI components separate. It does not need to be fancy for a simple app, a minimal MVC-ish separation of concerns might suffice.
I also hit this problem and i found a link which gives a good example how to seperate the controller from the view using the NetBeans GUI builder.
Here is the link.
I am writing a code that involves composite pattern and would like some clarification. I have Super Manager, a Main Manager and Ordinary Manager and they are in a descending hierarchy with the Super Manager at the top.
I would want the Super Manager to be able to give Main Manager some money and Main Manager to be able to give Ordinary Manager some money. The problem I have is I don't want Main Manager to be able to give Super Manager some money and I don't want to use instanceof to ensure that, since it defeats the purpose of Composite pattern.
My Main Manager and Ordinary Manager extend an abstract class called gradeManagers while my Super Manager has an array list to be able to to add components of type gradeManagers.
It doesn't sound like your hierarchy is a great fit for the Composite pattern. The Composite pattern is meant to allow a collection of objects to be treated in the same way as individual objects. (Think of parts being bolted together. Sometimes you want to think of a sub-assembly as a single part that can be bolted together with other parts/sub-assemblies. The sub-assemblies are the composites.) If I understand what you are trying to do, you don't have a collection of Manager objects that you want to treat as another Manager.
Nevertheless, whether or not you use Composite for this, I suggest adding a property (let's call it depth) that increases as you go down the hierarchy. You can then use this to implement your business rule: a Manager can only give money to another Manager of equal or higher depth. This allows you to code in a way that avoids any notion of object class.
As it has already been mentioned by Ted Hopp, this doesn't sound like something where you'd use a Composite Pattern. This just sounds like a case of polymorphism.
Composite Pattern should be used when you want a group of items to be treated as one. Consider a drawing program where you can place shapes on a screen, this could be triangles, squares, etc. Now, consider a functionality where you are able to change the background color of those shapes. If you wanted to change the background color of multiple shapes, you'd want to do something like this
interface Shape {
public void setBackgroundColor(Color c);
}
And in your actual implementation code:
for (Shape s : selectedShapes)
s.setBackgroundColor(c);
Instead of doing this in the code, you could use a composite pattern. This allows your implementation code to be completely oblivious to the fact that the "shape" you want to edit is actually multiple shapes, and allowing your application to treat it as any other shape.
class CompositeShape implements Shape
{
public void setBackgroundColor(Color c);
for (Shape s : Shapes)
s.setBackgroundColor(c);
}
class TriangleShape implements Shape { ... }
class SquareShape implements Shape { ... }
I would extend #Ted Hopp's answer and suggest that instead of depth you could use grade. This might be closer to the domain you are working with. Since you already pointed out that you do have grading managers this may be an elegant solution.
Hope that helps.
A shout out to the Swing gurus out there!!
I've been doing Swing programming for several years but have always been unclear on this.
As you know Swing/AWT gives you several ways to execute a particular action when a button is clicked. I've seen it done several different ways in the applications I've worked on. The project I'm currently working on tends to follow this approach:
someButton.setActionCommand("mycommand");
someButton.addActionListener(listener);
--snip--
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("mycommand"))
doThis();
else if (command.equals("someothercommand"))
doThat();
etc.
This seems kind of clunky to me - is there any benefit to this style of programming, or is it better to use Swing Actions?
Or are there different situations where the different approaches are better/worse?
IMO, it is better to use separate listeners for Actions.
That way you leave the delegating of what action should happen up to Swing. You don't have to compare Strings to decide what to do.
Having one huge ActionListener for more than one action feels like breaking the pattern to me.
From a design point of view, I think it is better to have one class to handle one specific action for a component as opposed to one class that is a "lets handle everything for all components here" type of design.
Also, if you use Action you can a) apply it to more than one component (e.g. a button and a menu item) b) call setEnable to enable/disable it for all components its attached to and c) Also use it to define various settings on the components its attached to (namely, the text label, the tooltip text, the accelerator key, icon, etc.). This last one is done via the putValue method and calling this method again will change the settings for all components its attached to.
Specifically, I would advise to subclass AbstractAction for your needs.
I know that's demo code but since you're working on this stuff I thought I'd mention that swing tends to be really repetitive if you're not careful.
Using Action classes tends to let you refactor better. In swing, one of the best ways to start is to ensure that NO strings are in your code. Nearly every "New" will be in a loop of some sort, reading from a dataset (Often the dataset is as simple as an array)--Once you start reading from a dataset like that, actions can help you a lot.
You use data to create your action, data to create your control, and data to associate the two--in this way you can end up very close to (or at) 0 lines of code for a new control.
Once you start programming this way and can see the patterns, it's at least as quick as the repetitive way and much less error prone.
its Useful if you have several buttons or components that perform the same action (ie. several exit buttons on the same page will use the same code)
Set them all to the same action command and they will all use the same code in the listener
JButton.addActionListener(this);
JButton2.addActionListener(this);
JButton.setActionCommand("exit");
JButton2.setActionCommand("exit");
public void ActionPerformed(ActionEvent e){
if(e.getActionCommand=="exit")
System.exit(0);
}