Hey again
As you can tell, I'm working on an assignment. After talking with my tutor yesterday, we need to implement MVC by having a single Controller class.
For example, I have a MenuPanel (with menus, menuitems) and an EntryPanel (text fields, buttons), that need to be controlled by Controller (original, I know). The underlying models to these only exist for EntryPanel (MenuPanel has no model, it's only a means to do stuff, not store/change data). From my current knowledge, I know I need to implement listeners, and have the controller handle them in some way.
What I can't see is the connection between all three parts - what code goes into the View, Model, and Controller. From an earlier assignment that we did in a different subject (that uses some MVC) I've determined that a View is constructed with a controller [class View (Controller controller)] and the Controller will implement something like View.Listener. Am I correct in these surmises, and are they any good articles on the net that talk about this?
Thanks. (P.S: The image thing works beautifully now
)
Posts
The view code should only be concerned with presenting data. There should be absolutely no business logic in it. In practice a little bit usually seeps in but ideally it should be only concerned with presenting the model that it is given.
The model is an abstraction of the domain of data you are dealing with. The model also typically doesn't contain any business logic. Any logic in the model is used for translating from one form to another (I have a string of a date, I need a double representing time since x, etc).
The controller translates and passes elements of the model to the view. Almost all of your business logic should be in the controller.
I'll see if I can cook up a short Java program to illustrate this but basically you want it set up something like this for a simple input->popup type program.
View elements:
input - text field
popup - joptionpane (or whatever) that shows a string to the user
Model:
String message
Controller:
router - takes input string and passes it to popup
You would make the controller implement ActionListener and register it with the input view. When the user enters text and hits enter that event will be sent to the controller. The controller would update the model with the value of the text field and alert the view that it had completed operation (there are quite a few ways to do this). The view would then take the contents of the model and display that using a popup.
I hope this makes some sense.
Assuming somebody doesn't beat me to it, I'll see if I can throw together a sample program illustrating it.
IView:
View:
IController:
Controller:
MVCTest:
EDIT: How do I process different methods? (instead of just having process() ), as Controller will be controller about 3 classes eventually, all with different methods.
EDIT2: Also, I receive input/events/actions in one class, and have to perform stuff in another class, how do I go about this?
Question 1: There's no simple answer to this. How you do it is a matter of requirements and coding style.
I'll see if I can modify my example to include both of your edits and post it up when I'm done.
IView:
View:
IController:
PrefixController:
SuffixController:
ButtonListener:
MVCTest:
One thing to note when designing listeners and controllers, you want to make them based on their intended function not necessarily on the type of component that invokes them. If you were writing the logic for a login page you'd want something like a LoginFormListener rather than trying to use one Listener for every single TextField. This isn't an absolute rule, it just makes code maintenance easier.
EDIT: I'm getting an error that the new controller's aren't implementing actionPerformed - are they meant to?
Also, to give you the best example possible, I have a text field in an EntryPanel class and a button that will "submit" an item (whatever is in the text field), and as part of the process behind that, must update an image in a different panel, ImagePanel. (I also need to update about 2-3 other panels, but that's just an example).
This is the order of things:
1. Place button on gui
2. Create your controller object
3. Create your listener object
4. Call associate on your listener (this adds itself as an ActionListener)
5. When the button is pressed the button listener looks up which controller is associated with the button and calls the process method.
It sounds like you are trying to set the controller as the ActionListener. My example will need to be modified if you want to use it with a text field and a button (since it's just taking the label from the button as its model). I don't think it should be too hard to do though.
RE: Listeners and Controllers - I don't think I mentioned the need to separate them, unless you read that in one my examples? *shrug*
I guess I misinterpreted this then, oh well. You don't need to separate your listeners and your controllers.
Your example is perfect Philodox, but I'm afraid it's just too complicated for me. I had to look up what a Hashtable was :P. This is the way I see it (code-wise) needing to be:
1. In a class with a button (or menu item), add an action listener that tells the controller class to listen to it
2. In the controller class, have an actionPerformed or similar that responds to all the events from buttons/menu items and does a specified method (pure example: so if I push a Print menu item, the controller would run a controller.print() method or similar)
In this, the controller needs to know about all of the potential objects that it needs to listen to and (from my research) I assume thats what the Hashtable is for. To me it would seem that the Hashtable needs to consist of keys and values such as this:
EnterItemButton, entryPanel.EnterItemButton (as a reference to the object button)
etc for each button
Or am I completely off track?
MAJOR EDIT: I think I got something working, by using my own code. I've made it so that my GUI instantiates the Controller, then my Entry Panel is instantiated with a parameter of controller, which it uses to set as it's controller and to tell controller to listen to it. I then have controller implement ActionListener, and I have it printing out the source of the ae and the getActionCommand.
Holy crap that took a lot of thinking. Is this a decent way of doing it, Philodox? At this point I don't much care for "proper" MVC - this is MY way. :P
EDIT: So I don't make a new post and bump, can java return arrays of objects? It won't seem to let me return a Product object (that I've made).
You can return any valid data type in java (which includes arrays of objects). Maybe post the offending code? It should look something like
I'm having trouble now with a textfield and .getText(). It constantly returns "" (empty) even though I've just typed stuff into it.
I access it from a method in that class that returns it to my controller class, however even if I try to system.out.print it from there, it is empty. Any idea?
Controller:
I have a method in controller that sets entryPanel to the parameter. My GUI creates a controller and passes it as a parameter to EntryPanel, which calls setController on itself - setController does this:
EntryPanel.setController
All of this is academic however, as in the EntryPanel.getItemID() method, if I System.out.println() it, it still shows up as "" (empty string).
Completely stumped on this :S
EDIT:
Then Controller handles it with:
The only result I've been able to get where it ISN'T empty is when i precede the line with a setText()
In your getItemId() put a setText(...) and see if that actually changes the value of the text field on the gui (it should).
Thanks.
In a previous thread, I wanted to draw an Image, and ended up using paint(Graphics g). It works fine. For the first image. Subsequent images leave ghostings of the previous image, as well as one of my textboxes. I call repaint() as part of my setImage() method as well, and draw the image with g.drawImage(). Any ideas?
EDIT: Another question: I have a class called Product, and two classes that extend Product, UPC_Product, and Non_UPC_Product. The Non UPC product has a method called getUnit().
I'm using instanceof to determine whether a variable (Product product = new...) is of either instance. If it is Non_UPC, I need to use getUnit(), but it is complaining of not being able to find the symbol. Is this because it thinks product is a "Product" and not a "Non_UPC_Product" during the compile? And how can I fix this?
Are you casting right?
EDIT: I got the image stuff to work. Weeee.
Don't forget you can simplify that if you only want to call the method
Though it makes it harder to read, it's a little more succinct.
Also, don't forget if you're only want to call the getUnit() method on your implementation of Non_UPC_Product you can use this instead
This should only be done if you don't want using anyone else's implementation of getUnit(). Otherwise instanceof is the better choice, since it doesn't stop others from extending your classes and reusing your code.
I'd generally go with instanceof I think, cos the whole point is to be able to reuse code
Thanks!