I'm creating my first "bigger" application in Java. As MVC is only pattern I know, I decided to use it. But there's something wrong with this concept.
For example. I need an Action (or generally event) fired from 2 places (from Button in frame and MenuItem). It has to do changes in at least 2 places and in the model.
I've got some ideas, but they seem wrong:
Pass the controller object to every view element, so newly created actions could use controller's methods to modify rest of the application.
Make controller static (for same reasons)
Make controller only model listener
Please tell me how to build it. Or give me some links to some easy to analyse applications.
Source of my project is here, if anyone wants to have a look: https://github.com/Arrvi/ColorExtractor
You are correct to use Action to encapsulate functionality for use by disparate components such as menus and buttons. A spectrum of examples is cited here. As regards MVC, recall that Swing uses a separable model architecture, examined here. In effect, the user is the controller, and not every interaction needs to pass through your application's controller.
Related
With all the tutorial out there, I managed to make a view displayed by a controller. However, I don't understand how do I allow the user to navigate through the site with MVC. Every request to the server must go through the controller? If every request must go through the controller, how am I supposed to let the controller define the type of response it should forward the request to.
Edit: I'm doing a school project which required me to convert my current not reusable code to MVC pattern but I'm not understanding the navigation part of different views. How to get from one view to another view. For example, the navbar element should point to the controller or the view?
The controller comes first, it comunicate with the model and send you to the view you want.
So, for what you need, in the view, just put some link with the url mapped in the controller you want...
The short answer is that all actions "point" to the controller with a parameter telling it what the action is supposed to be, together with any other necessary parameters.
Suppose you have a simple registration form. You may have the following two actions: showRegistration and Register. MVC is not specific to the web, but I will provide the examples in that context (based on your comments). These two actions will point to your controller (say index.jsp) with URLs like this: /index.jsp?act=showRegistration and /index.jsp?act=Register.
Your controller will then have different logic for the different actions (you can do it in many ways yourself, or use some framework which does this switching logic for you). At the end of the day the logic in the controller will boil down to something like this:
if showRegistration:
model.getCountries //to populate a dropdown maybe
view.showRegistrationForm
if Register:
model.validateRegistrationForm
if not valid
view.showRegistrationNotValid
else
model.createUser
if userCreated
view.showSuccess
else
view.showCouldNotCreate
The idea is that the Controller contructs the full action using reusable model and view components. You can use the same model.getCountries in many different places, thus reusing the logic of retrieving a country list.
In practice, it requires a nontrivial effort to generalize the model and view actions. I've seen many projects decent into a chaos of hundreds of components created for a single purpose and used only once, and many components which are essentially duplicates because the developer did not know a similar one already exists, or needed slightly different logic and did not want to bother modifying the old code.
I have been asked to revamp an existing JDialog that is a child container of an in-house Swing app. I will be re-writing the dialog from scratch and have been asked to lead the charge towards making the Swing app resemble a true MVC/MVP architecture (so my JDialog revamp will be the first of many pro-MVC changes to the app itself).
I understand MVC/MVP as it pertains to web apps:
Controller - is what the web app framework dispatches to handle HTTP requests; typically consists of multiple methods, where each "controller method" handles the request for a slightly different URL
Model - the DAO or POJO/bean representing call-specific data; controller fetches the Model from the DB and injects it into the View
View - the mechanism that ultimately produces HTML/JSP that will be sent back to the client/requester
This is not how all MVC/MVP web frameworks operate, but is the general idea.
But I'm struggling trying to determine how to translate this to a Swing app. In the Swing app, you have:
The JDialog itself
All the UI widgets (JButtons, JTextFields, etc.) that make up the "view" of the dialog
The action/event listeners for all the UI widgets which collectively make up the "business logic" for how the dialog will operate when the user interacts with the view
All the other "UI glue code" (setting which widgets will be enabled/disabled, setting their sizes and positions on screen, setting their tooltip texts, etc.)
Plus a lot of other stuff
So I ask: how do I organize all the code necessary for a functioning JDialog using an MVC/MVP architectural pattern? Also, if there are any articles, tutorials, or existing open souce projects that showcase MVC/MVP Swing apps, I am interested in them as well. Thanks in advance!
As discussed here, Swing MVC hinges on the observer pattern used to propagate model changes back to any listening view(s). As a result, much depends on the components in your JDialog. If your dialog must be modeless, the examples here and here may be helpful.
Since there are many valid recipes out there, I'll only discuss what I use: a modified MVP design which also borrows ideas from The Humble Dialog Box.
Basically, create your GUI with as little application logic as possible (zero is the goal). Create "presenter" classes (similar to Controllers) that have a handle to the GUI and inject the appropriate listeners onto the UI.
Some benefits:
Since all application code is out of the UI, your code is now 100% testable.
You can quickly prototype your GUI without having to launch your app everytime, which can be a big time-saver.
Separation of concerns makes code easier to read/maintain.
Your GUI code will be Swing only. A new team member who isn't familiar with your app but is familiar with Swing can jump right in.
With regard to Swing's implementation of MVC, we actually don't care. That's Swing's business. We assume Swing works (which it usually does). True, we need to know these sorts of things for writing custom renders, editors, models, etc., but those are details that the application framework (which is what I think you're asking about) doesn't need to know or care about, for the most part.
I would do like this:
MyModel model = engine.getDataFromDatabase();
myController.displayDataOnMyCustomView(myPresenter, model);
And at controller side, probably will remove a lot of listeners, set the data based on model, set sizes, locations and any other state representing stuff and finally re-add the listeners.
The myPresenter should be a custom JDialog with various basic ui elements (Component)on his UI tree.
I'm putting together a GUI with a couple of panels.
In one panel there are components for the user to input various parameters.
In another panel, there are buttons and a place to output a plot based on data
generated using the user inputs.
I have all of the various pieces working independently now I'd just like them to
talk to each other!!
When i hit one button, I would like to take all of user inputs and combine them to
generate a data set and plot it.
Another button then to write this same data to a file.
I have code to implement all the components individually, code to write data to
a file and code to generate a plot from data. All of which works fine.
I thought that I could use the Action/ChangeEvents to take the parameters and
assign them to an ArrayList. Then use this arraylist to generate the data.
I'm finding it difficult to plan an approach to tackling this.
Currently I'm using get set methods in the event handlers to set parameter levels for
a particular instance of the array list, I would like to pass this instance into another class to generate the data but don't know how to make it accessible.
I hope I have provided enought information here. If anyone has any
thoughts on this they would be much appreciated.
I think a structured way to tackle your issue is to apply the MVC pattern. Here is what I think a seminal article about Model-View-Controller (MVC) using Java.
Java SE Application Design With MVC by Robert Eckstein,
and here is another sample code.
As for taking the parameters from one panel and pass them on to the other panel, you can use the Command Pattern. What the pattern does is basically encapsulate all the information needed for a method to perform (an instance of a class, parameters, etc.) into one Command. This Command then can be passed around in the application, simplifying the way you execute the method.
A good book about Design Patterns, by the way, that I really love is Head First Design Pattern.
EDIT:
I'd just like to add some links discussing about MVC and some other GUI architectures that I find useful:
GUI Architectures by Martin Fowler
Build your own Composite Application Block series: UI Architechtures, Patterns and WinForm Examples
MVVM vs MVP vs MVC: The differences
This seems like a good case of application of MVC pattern:
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
Another good resource would be this book's second chapter:
http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?ie=UTF8&qid=1334437965&sr=8-1
I'm trying to use the MVC design pattern for my project but I'm sort of unsure about how to decouple my program into the classes. The first part of my program is a Login screen which requires the user to enter a their username and password and a start button which checks the details, and there is a button to go to a page where you can add a new user. So I was thinking for my MVC design:
loginpanelView : Just the GUI with the text boxes, labels, buttons etc
loginpanelController:
- implement the actionlistener for the start button here and have a reference to the method checkLogin
- implement actionlistener for add user button here and have reference to a method which switches the panels
loginModel:
- defines the actual method which checks the login
switchpanelModel:
- defines a method which creates a cardlayout system and switches the panels
My understanding is that the controller just makes very general references to what needs to be done i.e. sort of what the user wants to happen, then the model defines the exact method of how to handle this? Would someone mind verifying/ correcting my understanding please? I've read a lot about this design pattern but unfortunately I still don't feel like I have a clear understanding of it. Any help would be much appreciated!
p.s. Sorry! I forgot to include that I'm programming in Java
It sometimes helps to think of MVC in terms of dependencies.
The model repesents what your application does. It has no dependencies on anything. It is what makes your application unique.
The view displays information to the user. This information comes from the model. Therefore, the view has a dependency on the model.
The controller's function is to accept input from the user, dispatch that request to the appropriate model functionality, and (normally) accept the return value and supply it for a view to render. Thus, the controller is usually very tightly coupled to the view(s) that it serves. It also has dependencies on the model.
In this case, the model is your authentication scheme. (In reality, this is not all that much of a model but an entry point in your application, your overall model is something like "process payments", "generate report", "request to create widget", etc.)
You have two views, one to enter authentication information and a second for when an authentication succeeds. The first really does not have any model information, it is solely to collect input (however its design will be based on whatever the authentication model needs, so there is still a dependency here). The second will undoubtedly display a list of available features your application offers or display a landing page etc.
It is the controller's responsibility to mediate these interactions. Therefore, information sent from the first view is received by the controller, dispatched to the authentication model, authentication succeeds or fails, and then the controller chooses the appropriate view to render based on the result.
With such a basic "functional design" it's hard to help you exactly, but you might want to think more about the big picture about what you want.
A user model - database model for a user. Contains a "check login"
method
A login-page View - Form, layout etc
A login controller - Gets the stuff out of the form, tries to log someone in with the method from the user object, and create said user
object
The page view/controllers can be split up ofcourse in several sub-parts, but this might not be a bad place to start.
It seems to me that LoginModel and SwitchPaneModel are not models at all. Model is what you store somewhere. So you will have UserModel and PaneModel. And your controller will implement switchPane method and login method. It's good idea to decouple this method in some separate classes there are lots of methods to perform this task. But I strongly recommend you to find ready solution. Don't invent the bicycle.
A good place to start is here. This is a special case of MVC called Passive View. The first important idea is that the view and the model do not communicate with each other at all. The view only tells the controller about events, and the controller manipulates both the view and the model. A controller can even create new controllers and views (such as for complex modal dialogs). And finally, the model does not communicate with anyone!
So you have the right idea: your loginpanelController listens for button events from the loginpanelView, and then calls the right methods in the model to set the data and validate it.
I think one place you may be having a problem with is switchpanelModel. I don't think you need this. If your loginpanelView is the view with the cards in it, then your loginpanelController should be the one switching the cards.
I think models should be restricted to methods working with its own data, but must have no reference to any GUI element anywhere. Models do not drive the program; controllers do.
Rather then thinking in terms of 'defining' a method, perhaps it is better to think in terms of what is being encapsulated.
For example, loosely, in MVC a view encapsulates primarily the user interface of your program (a login form), a model encapsulates some part of your domain logic (password authentication) and a controller encapsulates the logic that connects a view with a model (it depends there are variation of MVC architecture). The controller is often to some extent coupled to a view (especially if you start adding overtly specific ActionListeners etc) however the model should be quite reusable/exchangable (changing how you validate should not mean you have to change any view/controller that uses it)
I have a simple java gui calculator, with 3 number systems (there are some bugs but that doesn't matter now). Currently all code is in one file. My task is to rewrite it as MVC, and add possibility to run it in either gui or console mode. How should I divide this program to organise it as M-V-C ? Is it written properly enough to add console functionality to it? (guess I'll have to change all methods invoking to JLabel Output to something simply storing an output String as a model argument and then having View to get it).
Here's the starting code :
http://paste.pocoo.org/show/224566/
Here's what I already have :
Main :
http://paste.pocoo.org/show/224567/
Model :
http://paste.pocoo.org/show/224570/
View :
http://paste.pocoo.org/show/224569/
Controller :
http://paste.pocoo.org/show/224568/
I don't have view in my model so I can't call to Output. That's the first problem I can see.
The current separation looks good. Here are some pointers for implementing the console view:
expose the controller's actions in a UI independent way. Such as an abstract Action class. The view then invokes the action in response to UI gestures. This keeps the controller independent of the view implementation, and allows the same controller to be used by multiple views.
add notifications from the model of changes, to keep views in sync.
The Console View can then read standard input, and write status to standard output by querying the model, and invoke functions using the Actions exposed by the controller.
A good test of MVC is creating two views on the same model and controller - both should work correctly and update from changes from the other.
You should get familiar with the Observer pattern. This pattern will allow your model to change any time, but without the need to know the different views (which is what we are looking for).
Simply put, the model will say: "Hey, I've changed. Anyone who is interested should act accordingly".