First time posting a question on StackOverflow, so please go easy on me :)
From what I understand, proper use of the model-view-controller pattern requires that we decouple the view and controller such that the view knows nothing about the controller. I'm having a bit of a problem understanding how to do this using Java Swing.
Say I have a view (some class that would extend JFrame), and this view has a button. Is it safe to say that I would want to register the controller as an ActionListener of the button? Or do I make it a listener of the entire view itself.
And how do I go about doing this without doing something like:
button.addActionListener(myController)
in the view, because if I were to do this in the view code, wouldn't it now have a dependency on the controller?
I didn't post any code because, frankly I don't have much to go on at the moment.
any help is appreicated!
It might help to not think of the view in terms of buttons etc. so much as an interface. The interface makes it possible for web ui's, command line consoles, etc. to be written and fulfill the role of the view.
In the case of your button event, the button represents a call to some command carried out by the controller.
So, you could have an interface like this:
public interface MyViewIf {
// used by the controller to register its self as a listener of the view
public addViewListener(ViewListener vl);
...
}
and:
public interface ViewListenerIf {
// used by the View to notify any listeners of control events etc.
public onViewEvent(ViewEvent ve);
}
Then your controller would implement ViewListenerIf and register it's self with a factory generated instance of MyViewIf. That way the controller doesnt need to know any specifics about your view class(es).
Your view class would then internally handle it's own button events, turn them into ViewEvent objects and call onViewEvent() on the controller that registered it's self with the view, leaving the View 100% oblivious to the existence of the Controller.
Make an actionlistener in your view class. From your actionlistener you call your controller.
Code for actionlistener:
controller.doButtonClick();
This means you need to inject your model and controller to the view. That is how I do it.
Take a look at the Spring Framework to get an insight in implementing the MVC pattern.
Brief Spring tutorial Tutorial
Related
I have a question about Model View Controller.
I get confused about how View and controller can communicate with each other.
I have a view class which takes in a model instance:
View v = new View(model);
I have also got a actionListener field in the View class and in that constructor I am passing in a model and the instance of the current class(view):
private ActionListener listener;
.
.
.
listener = new Controller(model,this);
Now in my controller class I have extended the ActionListener and passing in the model and the view class:
public class Controller implements ActionListener{
public Controller(model m, View v){
.
.
.
Now my question is, can you pass a view class in the constructor of a controller class in model view controller? Reason why I am passing in the view is that I sometimes want to close the view window or want to pass in the values from a textfield. Also sometimes I want to invoke a method from the view class. Is this the right way of doing MVC?
Thanks
You can ask 5 different people how to implement MVC and you will get 5 different answers. There are so many different ways to do it. I would read more about MVC and other design patterns such as MVP. Martin Fowler has some great articles on GUI patterns . There is also this article which has great info.
To answer your question. There is nothing wrong with the controller knowing the view. The controller is the one that should be handling the user input (other wise you could consider MVP). I would create an interface and only have the controller know an interface for a view. So create something like IView and have your view realize that interface. That way you don't have a tightly coupled view and controller and you can do things like creating a mock view for testing.
I have a app on Google App Engine and I'm using GWT, and when the user goes to www.myapp.com/#show I need to show a graph, and in that page there is a button to search and add nodes to that graph, when the search Button is clicked I need to show a popup with the search form (it has several functions and dialogs).
Can I create a view for that page and another view for the popup and use the same presenter for both?
or What is the best way to implement that based on the pattern MVP?
MVC(Model View Controller) style tells that you have this three packages for Entities, UI, Controller classes. This help you organize your code and break it to plugins.
As for your question it is better if you can implement a CustomPopUp class in the View(UI) package and make it abstact. So PopUp could have as parameters the message the context or everything it needs to show the approprate message.
And you can pass CustomPopUp as private delegator to your UI classes who need to show popup messages.
I know how classic MVC looks like, but I was asked to write game using other type of MVC. I mean something like this : Draw which show my lecturer
BQ is LinkedBlockingQueue of Events. And I don't know how in this situation model can tell view and controller that his state has changed? My antoher problem with this MVCis fact that Controller shoud make deccision about consequenses of Clicked Button, but again, there is no connection from view to controller. Is it means that View should implement ActionListers inside of it?
It seems to me that the diagram shows the view generating events and placing them on a queue. The controller is reading from the queue and updating the model/notifying the view accordingly. To me this is still MVC.
How does one most efficiently connect a view and a controller in a MVC-esque Java application. Currently, I'm doing the following:
Controller creates view and passes itself into the view as a parameter:
MyView view = new MyView(this);
View has ActionListeners for buttons. ActionListener doesn't do much but fire an action in the controller:
private class ButtonAListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent arg0) {
controller.clickedButtonA();
}
}
It is working OK, but is this acceptable? For example, if a button is clicked in the view, the ActionListener passes that information into the controller, which does some calculations, and passes back a command to update the view.
IMHO it is acceptable. I think any solution is ok, as long as no tight coupling occurs. Depending what GUI library you are using (AWT,SWT, Swing..) different classes are appropriate though. Btw. you should check adapters out (if you dont know them already): http://blogs.oracle.com/CoreJavaTechTips/entry/listeners_vs_adapters
I'd recommend moving the creation of view from the controller. If view and controller are to separated (and that's the whole point), the controller should only have a setter method (or other dependency injection mechanisms). I think you should have a launcher class that creates the controller and views and then connects them together.
I need help. I am struggling to get my Observers working in java. Can someone explain to me using MODEL-VIEW-CONTROLLER Architecture how to create and observer from View To Controller.
This is because if i press a button on the view the action event has to call notify the controller of that button being pressed.
For that I'm implementing observers to minimize class coupling.
I have a class Controller, View (Swing using JFrame), and an Application Class that holds the main method.
I tried implementing it so that Controller implements Observer and the View extends Observable.
After triggering the event of clicking the button all code except the notifyObservers("OBJECT") gets called. It disappears somewhere in the java library.
Any Help Will be much appreciated.
the model should extend observable and the view should implement observer (you want the view to depend on the model). you will need to call setChanged to after you change the state of the model to force the observers to be notified.
Double check, that your controller is really observing/listening to the (correct) button instance. Use a debugger and set some breakpoints to check whether notifyObservers is called and who is receiving the notification.