I learning the MVC model by building my daughter a flash card application so she can practice when I am not home to practice with her. So far I have 4 classes. FlashCard(model) FlashCardSet(view), FlashCardUI(view) and FlashCardApplication(controller). I'm not sure if these are classified correctly but I am still learning. Since the MVC goal is to keep the UI separated from the model and create the links in the controller, I the controller to know how to update the FlashCard(model) when something on the FlashCardUI(view) is clicked, checked or etc. A class that manages all the user actions of the application where I could connect the model to the views. I guess that describes what the controller's job but I am having a hard time figuring out how to implement it and keep the MVC separation.
Should the UI class expose the swing components to the controller like...
Or can I create some sort of FlashCardAction class that can be passed to the UI? If this is the best way, could you provide some examples? Thanks for helping me impress my daughter and learn a little bit more at the same time.
It seems like all us dads are trying to program a java app to interact with our kids! (There's a recent post by one of the forum mods about making a paint program for his son.)
I've got 2 apps, which are pretty similiar. One switches shapes every time she clicks the button. The other switches from a shape to a picture of family members.
Even though MVC is great, it may be a little overkill for what you are trying to do. IMHO. The approach I took with the above, which sounds about like what you are doing, is to make 2 classes.
A ShapeButton knows how to draw shapes when its clicked. It doesn't know about anything else. It has an innerclass acting as the ActionListener, though I could have just implemented the interface as well.
The MainProgram simply sets up the screen, layout, and adds the buttons to the panel. It doesn't know anything about what the buttons do.
For the second program, nearly the same thing happens, except the MainProgram2 class holds an array of ImageButtons and adds a generic button on the bottom of the screen. When the bottom button is pressed, it cycles the currently displayed ImageButtons with the next set of four.
If you'd like to see them or get the source code, let me know.
Regards, Aaron R>
Joined: Sep 15, 2003
Thanks Aaron. I would love to check it out and see the source! Thanks alot! I am really interested in how you connected the two. I wanted the actionListener class to be generic enough to handle all events that would occur in the application so I would know exactly where to debug and add functionality. Would that be a good approach or should I just add actionListeners to every gui component on the app? That seems to be the most popular way but it seems like there should be a more efficient approach.
[ May 26, 2004: Message edited by: Chris Ramsey ] [ May 26, 2004: Message edited by: Chris Ramsey ]
If you're creating your own UI classes, you could benefit from reading up on the PLAF packages. The UIManager follows an intricae contract when determining and configuring the UI delegates for a JComponent.
Please excuse me if I have misunderstood your design, but:
The view (as you describe it) contains controllers (buttons) which affect the model. The model then lets the views know that they need to update themselves. Your application class is only really a controller if some interaction you have with it causes the model to change. How are you interacting with the application? The user interaction represents controller, view what you see and model the data.
Maybe a clearer way to think of your design would be to have a panel full of controllers which simply listen to whether they have been interacted with by the user, a model class and separate panels with different graphical views which show the current state of the model class.
You can make your data model Observable, the views implement Observer. When you interact with your controllers e.g. click a button, the button's actionListener's performed action would be to cause the model to change in some way. The model sees it has been changed and notifies its Observers.
I think possibly your application class is a bit of a red herring for you. It doesn't mean you are not allowed one, just don't think of it as a separate part of MVC unless it fulfils one of the three types.
HTH Regards, Ken
Joined: Sep 15, 2003
Thanks Ken. The purpose of my FlashCardApplication class is to connect the UI components to the model. I guess I am thinking incorrectly about how this implements MVC. For example I have a skipButton in the FlashCardUI class. This button should skip the current flashcard show on the screen and retrieve the next card from the FlashCardSet (and arraylist of flashcards) Are you saying that the skipButton is the controller, the FlashCardSet is the model and the screen would be the view in this interaction? Is MVC implemented with each interaction or within the application as a whole. Another interaction is when she answers the flashcard equation. She enters the answer in a textfield. The textfield should pass the value entered to a method that checks her answer against the flash card answer. The view should reflect whether the answer is correct or not. In this interaction would the textfield be the controller?
Allow me to give you more details about my design. Maybe you could help me start thinking and coding in the right direction.
The FlashCard(model) knows how to do the flashcard stuff. Some of its fields are numeral1, numeral2, equation and solution Some methods are... getNumeral1(), getNumeral2(), createEquation(), solveEquation() Each card has its answer stored in solution.
The FlashCardSet(controller to FlashCard) which extends ArrayList...is a set of FlashCard objects. It holds and manages which FlashCard is presented. Some of its methods are ... loadFlashCardSet(), getEquation(), skipEquation(), clearEquation()
The FlashCardUI is all the gui components. The buttons, the answerfield, flashCardPanel where the equation is displayed
I want to FlashCardApplication to be where all the pieces fit together. The FlashCardUI class will interact with the FlashCardSet class. When the skipButton from the FlashCardUI class is clicked I want the FlashCardSet class skipEquation() method to be invoked. So would the FlashCardUI.skipButton be a controller to the FlashCardSet.skipEquation() method? Seems like MVC is implemented on a per interaction basis and not by the classes as a whole or is it? The problem is I want the connection between the button and the method to take place in the FlashCardApplication class. Bringing me back to my first question. I'm thinking the FlashCardApplication would have an inner class called FlashCardActionListener that would be an ActionListener. It would be responsible for listening and calling the appropriate FlashCardSet functions when the FlashCardUI buttons are clicked. How would I go about doing this? How can I connect the FlashCardActionListener class with the FlsahCardUI class reference created in the FlashCardApplication class? Should the whole FlashCardUI be an ActionEvent that passes an actionCommand to the FlashCardActionListener class? Am I confusing you, because I think I have just confused myself. Help!
What I want is a connection from FlashCardUI and the FlashCardSet
Joined: Sep 10, 2002
Breath breath breath!!!
Ok, you want a flash card app, that lets your daughter do the following -
- See flash cards - Enter the answer - Get feedback about the answer (wrong or right) - Skip to another flash card
My thought is you need some general classes along here -
- A flashCard class with a getSolution method and someway of loading or setting its 'problem', this class could extend some gui component
- An application class such as FlashCardProgram. This would have an array of FlashCards. It would also have 1 maybe 2 actionListener classes. One to handle the checking when she types in the answer and another for skipping. You could make one class that checked to see who called the handler. (Thats if I am remembering correctly about a button and a text field both using an ActionListener) This class could also handle the displaying the 'That's Right' or whatever you want to do when she gets it right.
Now, I know I didn't mention MVC, but thats ok. MVC is really for large apps, IMHO, where you really need to ensure the components are seperate from each other. Think of teams of programmers, where some specialize in gui (how your cards look, color, font, size, etc), others in program business logic (when the answer is right, the current card is removed from the list), and others in how the program should 'flow' (the actionListeners, sort of).
You should be able to do what you're trying with very little complication. For example you said you extended the ArrayList class. Well, thats ok, but you could have simply wrapped it with the class you mentioned. You could also just dispense with the class entirely and have the main application class hold and array of your flash cards.
I'll email you the 2 apps I was talking about. I don't have the source for them right now, but I will add it.
Regards, Aaron R>
Joined: Mar 26, 2004
I spend most of my life confused!
Are you saying that the skipButton is the controller, the FlashCardSet is the model and the screen would be the view in this interaction?
Yes, except the screen(sort of). The view is an interpretation of the state of the data in the model. You can have many different interpretations of the same state at the same time.The screen is not a direct interpretation of the model.
For example, you can have a pie chart and a bar chart both interpreting the same data. If you change the data in a spreadsheet cell, in an MVC interpretation both the pie chart and the bar chart would be informed that the state had changed ( either directly by the controller or by the model: I think this is the difference between a 'pull' or 'push' approach) and would redraw themselves. The views are responsible for their own interpretation of the data which they get from the model but they shouldn't contain the logic which decides how the model's state changes.
I want to FlashCardApplication to be where all the pieces fit together.
1. Put all the data and logic in one place and call that you model. 2. Give the model a publicly available API which any controller or set of controllers can hook into. 3. Define any number of controller classes with which the user can interact and which use this API. 4. Define any number of views which interpret the data when told to. 5. Compose all the parts in your application class.
FlashCard and FlashCardSet look to me to be your data and logic which together make up your model. If FlashCardUI contains both controllers and a view of the data then it is both view and controller. This is not wrong. In fact Java makes use of a similar approach in its Swing components. You could think of a FlashCardUI which is composed of a FlashCardControls class with the user interface part and a FlashCardView which is a view. Alternatively, your UI could be composed of FancyFlashCardControllers and FlashCardUpsideDownView or all of these or more views and controllers. All that is important for MVC is that each of the three parts is independent from the other.
Now back to your specific examples ( sorry for being so long winded ).Here's a possible approach.
You click on your skip button. The skip button has an ActionListener whose job is to call the model's skipEquation() method. The model in turn carries out the necessary calculation (which is presumably to increment currentFlashCard). The model then calls notifyObservers() etc. , the view (which has been added as an Observer of the model) calls its update() method which has a peek at the data in the model and redraws itself according to whatever scheme it has.
Let's rough out a framework for this.
Regards, Ken E&OE!
Joined: Sep 15, 2003
Thanks Ken when I am going to try to work it out this way too.
subject: Adding an action listener to an entire class