Design Issue: MVC model with Java CardLayout application - java

Sorry for the vague title, I am trying to layout an application i have unfortunately starting coding without following proper MVC architecture rules. I have an application that has the following structure.
JFrame with a JPanel ("MainPanel") added as a component and the MainPanel has a CardLayout structure. The MainPanel then has several JPanel's that are flipped through using buttons, Jcombo Box and List selections.
I want to implement the MVC model using this structure and i am having difficulty finding a way to accomplish this. So far i have all my actionListener's inside where i created the GUI components and want to separate that out and have a controller for each JPanel added to the MainPanel. What are some ways i could design this program in a way that i can seperate my action logic and data accessing and still maintain a CardLayout structure?

As noted in A Swing Architecture Overview, the Swing separable model architecture means that an application may have many models. Buttons and tables are common examples. Actions are a convenient way to encapsulate the functionality of components for reuse in menus, buttons and other controls. You haven't given much detail about your application's model(s), but you might look at using the state pattern to simplify your navigation model. This answer may also offer some insight.
Addendum: As a concrete example, the navigation model used by CardPanel is entirely implicit in the combo's DefaultComboBoxModel. By extending that model, your views may register themselves as listeners and configure themselves appropriately when the user changes the combo setting. For example, a value needed by your program's data model, to which the relevant view also listens, may be highlighted to signify a required field; or a control that makes no sense for the current state may be disabled or hidden.

Related

Looking for a GUI design-pattern that fits this application

I'm developing a desktop app in java for a school project and I want to know how should I be designing the code of the GUI, specially because I will later have to run JUnit and functional tests on the app. I know it kinda sounds like an opinion-based question, but all I'm not asking for the "best" method, I just want to be pointed to a specific design pattern that can fit the need of my app.
To elaborate a little more on the type of application, it's "stage based", one button leads to a different section of the app. One main window, only error or warning popups (only one frame).
My current approach so far:
So far I've designed 3 different JPanel classes using eclipse's WindowBuilder (main menu, admin menu and user menu) and a AppGUI class that creates and empty frame with a CardLayout layout and fills it with one of the 3 panels (starts with main menu). Then the buttons on such panels point to the next panel. (Example, main menu -> user menu -> create profile)
The panels need to communicate with the AppGUI instance in order to execute the panel changes and later on, the functionality that the other options will have. To do this, I've been passing the AppGUI instance as a parameter to the panels on initialization and storing it inside each panel (I first thought of having a singleton AppGUI and have static reference to it, but I later on read that it's bad practice, specially for later mock testing).
Also I'd like to have the logic for the application on different classes other than the GUI classes and I'm not sure if passing the AppGUI as parameter to every method out there is good practice or not
In conclusion, it would be great if someone could point me to a specific design pattern for this kind of GUI, thanks in advance!
I would suggest the Model View Controller (MVC) pattern.
The idea of MVC is that the models (your app logic), the views (UI elements), and the controllers all work together. The models and the views are completely independent of each other i.e. you don't pass a model class object to a view class object or vice versa. The models and the views should talk to the controllers and the controllers makes all the decisions.
Controllers
They contain your app's UI logic, like how to layout the views. They are notified by the model once in a while (e.g. some data have changed!). They are also notified by the views (e.g. the user pressed a button!). And controllers need to respond to these notifications. For example, when the user pressed a button, the controller might tell another view to show, or tell the model to do some calculations or some other stuff. In your case, your controller is most likely to have all the ActionListener for the buttons and text boxes on the UI.
Models
They contain your app's logic. Try to design your model to be UI independent as much as possible. If designed correctly, your model should still work without the UI i.e. you should be able to make a command line version of your app without changing the model. For example, if you are making a calculator, the model should do the actual calculation.
Views
Most of the time, you don't need to worry about this part because swing already provides you with lots of view classes, such as JButton, JPanel, JTextArea etc. If you happen to be creating your own views, remember that it should not contain anything related to the model i.e. the view should work fine with a different model.
You can always search for more info on the web.

JAVA Swing MVC - Main Controller?

I'm having some troubles designing the architecture of an application I'm trying to develop. I'm working on JAVA, and I started working on this application because I want to deepen my overall knowledge of JAVA, architectures and patterns. I want to follow the guidelines to make a reusable, low coupled application, like it should be. The application has only one JFrame, but inside it there are several JPanels, each one representing a module of the application.
The question is: in JAVA Swing, how to implement an appropriate MVC pattern?
I struggle on how to understand the way it should be done.
Should I have a main Controller class, that holds references to all the other Controllers?
(I have an image to demonstrate this, here: https://docs.google.com/file/d/0B7tBdn5slIFeY2FoSmxESTREQ1k/edit?usp=sharing)
And in this case, should all the events that require changing the module that is being presented redirect to the main Controller?
Or should I just couple the JFrame with the Controllers of the application, and communicate directly with them?
Basically, I would like to know if i need to have a class that 'manages' all the others.
I have already read several explanations, and different opinions, but I believe this is a little more specific.
Hope I have made myself clear (and hope as well that my explanation is better than my drawing :)).
EDIT:
a sample of the application usage:
One (an only one) JFrame throughout all the lifecycle of the application;
the menu will be on the left side, as in BorderLayout.WEST;
the current module of the application will be in the center, as in BorderLayout.CENTER;
when the user presses one button of the menu, the corresponding module is loaded into the BorderLayout.CENTER;
Should the menu (View) have it's own Controller, and this Controller communicate with the JFrame? And the JFrame load the new module into it's Layout? Or should the JFrame have its own Controller (or Model, as Gilbert Le Blanc said)?
I know this may seem to specific, or easy to understand, but everytime I think of an desktop application, I struggle to understand this.
When you have an application with a GUI, the GUI model becomes the application view. The application interacts with the GUI through the GUI model.
Or should I just couple the JFrame with the Controllers of the application, and communicate directly with them?
This is what I've done. I've packaged the controller classes together, but I've never created one main controller class.
I keep the GUI controller classes in a separate package from any other application controller classes, like the data access objects.
I usually put each JPanel in its own class, but I wouldn't call that a requirement. The JFrame has its own class, although the instance of the JFrame and the instance of the GUI model are passed to almost all of the GUI components. This makes menu actions possible.
This Traffic Signal GUI article goes over the basics of how to code a very simple GUI.
Edited to respond to the changes in the question.
The GUI controller is separate from the GUI model. The GUI model contains all of the data elements that make up your GUI. Strings for JTextFields, DefaultTableModels for JTables.
Based on your application design, I'd recommend that you create a Java class for every JPanel that you want to put in the center of your application. Your JFrame will control which JPanel is displayed, based on the menu. I'd also suggest that you look at the JTabbedPane which uses a different user interface to accomplish the task of choosing which panel to work with.
Assuming you're going with the menu on the left, each menu option (toggling JButton?) will have it's own controller method or class. These controllers have to have an instance of the JFrame so the controller can call the method in the JFrame class that puts the appropriate panel in the center of the display. The controller decides which method to call, but the methods themselves are a part of the JFrame class.
I've been talking about JFrame and JPanel classes. It's important that you use composition rather than inheritance to build these classes. The JFrame class contains a JFrame. It does not extend JFrame. The only time you extend a Swing component is when you want to override a component method.
As discussed here, Swing components use a separable model architecture with the model and view loosely coupled using the observer pattern. Not every GUI control has to be part of your application's controller. Using an ActionListener, such as Action, is particularly convenient for encapsulating application functionality.
Addendum: I'd use CardLayout, illustrated here to switch panels. Note how the Action handlers can be used with buttons, menus, combos, toolbars, etc. Each card's content can have it's own implementation of the MVC pattern, separate from the others. Use a PropertyChangeEvent, seen here, for communication between components.
In general, Swing components, e.g. buttons and tables, already listen to their respective models, leaving you to focus on your application's data model and its listening views. Conveniently, a Swing model, e.g. ComboBoxModel or TableModel`, can have more than one listener.

basic MVC pattern and GUI

I wanted to ask for a tip. How would you struct your application if you had a JFrame with many JPanels which have like ten JTextFields Labels, and an Edit Button.
Would you put all the code in the JFrame or would you extend from JPanel and include all of them in the JFrame?
What about the buttons? I want to use the MVC pattern, how would you handle the actionlisteners? Are each of them an own controller or would you use only one controller for all of them?
I think it's first of all a question of style and personal preference. It also depends on what your application should do and how.
If your JPanels all are very similar in a certain way it would probably make sense to extend from JPanel. For example if every panel had 10 Buttons where Button 1 does always action xyz() for its corresponding model-object (especially when this object is the same for all buttons of 1 JPanel) and Button 2 does abc() ...
If the JPanels are not strongly correlated in such a way I would place my code rather in the JFrame or in a third Object which sets the whole GUI up from outside.
It's similar with the actionlisteners. If you have very few actions I would probably go for just one controller-object for ease of use (not many files). If you have a lot of different actions I would group similar actions into one controller-object per group of actions.
That said it probably is best to start with a simple approach (YAGNI) where you do everything from the JFrame / third object and have one actionlistener and then refactor when you feel that splitting things up gives you a cleaner or more flexible design.

Swing desktop app - how to organise my code

We are going to use Swing for our next project which will be a lightweight desktop app.
I've been reading the Swing tutorials on Oracle's website and have started to get the hang of it.
I was told that instead of switching JFrame I need to work within one JFrame and switch JPanels.
My questions to you would be the following.
Can I create the JPanel designs (or their templates) in design mode (WYSIWYG editor) and call jframe.setContentPane(nameOfJPanel) or do I do them programatically in code?
Secondly, how do I structure my code... If I dynamically add new JPanels and bind their events to an event handler.. all my logic and code will be in one HUGE class with tens of methods. I just don't know how to proceed and nowhere can I find an example with multiple (more than 6 let's say) panels on the internet.
To WYSIWYG or not WYSIWYG
This is a debatable question at the best of times.
I encourage all my junior developers to start out hand coding UIs as it teaches them important basics about how to use layout managers and how to handle compound layouts.
This tends to take longer as you need to verify the layout with each change.
I personally use the form editor in Netbeans for most of my general work, but will hand tweak UI's
Structure
Think about boundaries of responsibility, reuse and reduce strategies.
What you don't want is some huge master class that does EVERYTHING. It will be difficult to maintain and update (I live with this horror every day).
Instead, identify the distinct areas of responsibility and either use getters and setters or models to move the data around the application. The more you can decouple your code, the easier it will be to update and modify.
Identify like work and model it as interfaces and abstract classes where you can. Basically where ever you start thinking about coping code is probably a good indication that your design is off and you should consider implementing abstract classes to cover the overlap.
Take advantage of the Action API for replicating commonly used concepts (copy and paste is an example of this. You would want menu items, possible toolbar items and maybe even popup items, these can all be handled by the same Action class).
Separate the data from view. As I said before, take advantage of models. The data shouldn't care how it is collected or modified, only that it can be. Equally, the view shouldn't care about how the data is managed, only that it is.
If possible, define interfaces between the separate areas of your application. This way you can further decouple of the application and no one part becomes reliant on any one implementation (hello my world :P)
Don't be tempted to simply dig through a component hierarchy to gain access to that field, it will produce a nightmare if you need to change the code!!
The JFrame will be the main window of your app and the panels will be the brick composing it.
You should create each panel in its own class and you can arrange them by functionality in packages. You'll have panels for holding content of logical part of your application and panels that contains real stuff.
A logical panel could be the main view and the menu bar. An application panel would be a form, a menu, a canvas...
You'll have to put application panels inside logical panel and to change the content of the logical in response to users actions.
You should study how layouts work in order to compose the view inside the JFrame and to layout components inside panels.
For example the BorderLayout is a classic when defining the main area of an application:
- menu and toolbar on top
- browser on the left
- status bar at the bottom
- main panel on the center
You can use WYSIWYG editor, but avoid doing all design inside the same class. Else you'll have an horrible HUGE class. Create your panels in separate classes and compose them in your main view.
You can use empty panels as placeholder to help you create the structure of your application.
You'll have to bind your domain data to the view in order to not mix the two layer.
Bind means that you will write a way to go from a java bean to a form and the reverse.
Basic binding is handwritten, but some tools exists to do that.
If it is a small application, it is maybe better for you to handwrite everything.
Building a Swing application can be very tricky (you'll have to know about the event dispatch thread, layout management, event management, widgets (label are trivial, but JTable can be very complicated to handle);
I'll recommend to find a book about the topic, and to find some open source swing application in order to study how it structured, before you start your project.
This is how I organize my code:
class Panel1 extends JPanel{
//code for panel1 and its Components
}
class Panel2 extends JPanel{
//code for panel2 and its components
}
// and it follows.
class ApplicationFrame extends JFrame{
/// LOGIC to switch between panels
}
class Main{
//contains main() function
}
Any HAND-CRAFTED GUI code, is better than a COMPUTER GENERATED WYSIWYG -APP Code.

Designing mvc controller layer

I am trying to understand and practice the MVC-pattern to improve my development. So I started refactoring an application I once wrote and have progressed so far. It is completely clear how my model looks like and also the view is ready so far. But now I am searching for a good practice to design my controller layer.
I have created a view that's split up in different main components. Let me give you a short example:
There are 3 Panels that group specific components:
"FilePanel", holding a JTextField and two JButtons
"DataPanel", holding all components neccessary to display some data and some JButtons
"CalendarPanel", showing some calendar-sheets
These three Panels are each in a separate class and afterwards instantiated and arranged in a GUI-class.
No the actual question. As I separate the Panels, how should I build the controllers? Should each panel get its own controller class (FileController, DataController, CalendarController)? Or should there just be one controller class for the whole view?
If I create one controller class for each panel, how do can I achieve that the controllers communicate with each other? Example: If a button is clicked in "FilePanel", how do I notify "DataPanel" about this?
Could you give me some examples of best practice?
Are the Panels fundamentally separate?
NO: The set of panels is fundamentally one state. For example the panels represent a console showing different aspects of the same items under control. The user selects an item and all the other panels update to show views of the item. In this case one Controller is enough.
YES: That is can each of them move through various states independendently? This is the kind of realtionship you might have in a "Portal" style application. The user can work in each Panel pretty independently - extreme example, two separate side-by-side browser panes in one overall viewer. It's the kind of effect you get in Composite Applications where the user has windows open on different back-end systems. Sometimes user actions in one window cause things to happen in another window, but generally they run separately. In this case we have can have separate controllers each responsible for the state of a Panel. They can communicate with each other by event handling mechanisms. User clicks in File Panel, View contacts its controlled, which issues a "File Selected" event, whose payload is the id of the file. Note that the "click" event is translated into a non-ui specific event.
By having separate controllers we decouple the details of the current set of panels. Addind a new panel requires only that the new controller registers for events.

Categories

Resources