MVC, Swing, Observer Pattern - Updating a Jtable - java

I am new to Swing. I am using the MVC architecture. I am unsure how to set up the observer pattern so that I can refresh a JTable whenever new data is entered. My model consists of an Immunization class, and a Visit class, along with a mock patient. A patient has a list of visits and a visit has a list of Immunizations given during that visit. Thus, I have 3 classes - A JFrame Main class called MainFrame, and 2 components - An ImmunizationPanel JPanel, and another panel that creates a JSelectBox.
The Idea is to start the main frame and load the two components, which will show an empty Jtable and a list of Immunizations to choose from in a drop down box. At this point the UI is very simple. The user is to click the SelectBox and then hit enter and it should update the Jtable with the value chosen in the SelectBox.
I have a few Controllers that provide the business logic. My question is, What classes do I make observer and observable? A problem I am running into is that MainFrame already extends JFrame, so it cannot also extend Observable. So should I only be using Observable and Observer in my controllers? At this point my table is updating only after the program is restarted and it loads the data at run time.
I can provide code if anyone needs to see it, but my question isn't about the code per se, it is about where to extend Observable and Observer. Do you use it in the View, in the model, or the controllers?
Thanks.

Related

Using swing GUI in java

I have a few questions about Java swing GUI, FYI this is my first time using a GUI so I really don't know much about this stuff
I have code that is basically a user class with name and number attributes which I plan to use as a login page. So what I did was create a new GUI class for this user class completely separate from the user class (as in one class for functions and another for the GUI). Was this wrong? as in should I have placed the user methods and the GUI in one class?
I have 2 GUIs, a welcome GUI and a login GUI. How do I ensure that one leads to the next? I tried to make the welcome frame invisible (the login frame is made visible in its own GUI) but that didn't work.
The login GUI is similar to the one above and has frame.setVisible(true);
1- I have a code that is basically a user class with name and number
attributes which I plan to use as a login page, so what I did was
create a new GUI class for this user class completely separate from
the user class (as in one class for functions and another for the GUI)
, was this wrong? as in should I have placed the user methods and the
GUI in one class?
A common concept in UI development is "model-view-controller" (don't worry about controller just yet). This means that your "data" is modelled in some way (ie User) and your "view" (UI) takes that model and makes decisions about how the model should be presented to the user. It also helps manage the interaction between the user and the model.
So, yes, keeping your "data" independent from your "ui" is the right strategy. Always remember, it's the UI's responsibility to determine "how" the data is formatted, the model is just a means to manage the data in some meaningful way.
2- I have 2 GUIs, a welcome GUI and a login GUI, how do I ensure that
one leads to the next? I tried to make the welcome frame invisible(the
login frame is made visible in its own GUI) but that didn't work
This is a little broader in concept. Typically, we might recommend using a CardLayout to "flip" between views, but this would assume you want to revisit those views at some point.
On a more "abstract" point of view, you would use some kind of "controller" to make decisions about what should happen based on the current state.
This means, if "welcome" has not been presented, you'd present the "welcome" view. When the user is ready to move beyond it, "welcome" would notify the "controller" and the controller would then decide what to do next.
ie. Do you have previously saved credentials or not? If so, you could auto login the user and move on, otherwise you'd need to present the "login" view in order to get the credentials and allow the controller(s) to authenticate the user.
This moves you onto the "observer pattern" (aka listeners), where an interest party registers interest in been notified when some state has changed.
When trying to design these kind of systems, always be asking yourself some basic questions
Just how much do I need to expose to other parts of the program? ie You're welcome view doesn't need to know about the login view, as it could do things to the login view which are out side of it's scope of responsibility
How hard or how much work would I need to do to change any part of it?! So you get the welcome screen to open the login screen, but now you want to add in "auto login", just how much work are you going to have to go to make that work? Would it have been easier if the welcome and login views were independent of each other and controlled through some other mechanism?
Take a look at Java and GUI - Where do ActionListeners belong according to MVC pattern? for simple implementation example

Using the Model-View-Presenter design pattern for a Java Swing application

I'm working on developing a Java application for organising personal music collections that allows the user to search their digital music library with the help of textual lists displayed in a table, choose songs for playback and provide information about them i.e. something like Rekordbox (https://rekordbox.com/en/).
After conducting some research on how to design and implement such a system, I came across the Model-View-Presenter design pattern and from what I understood it is a pattern that allows flexible , reusable and test driven code to be written.
So to come to my problem:
View classes: Assume I want to have a Swing UI that consists of a JFrame which has 3 JPanels inside of it as separate view classes. i.e. MainFrameView with MenuBarView, TablePanelView, PlayerPanelView which are created inside the frame (which is a view class itself). Those panels have various Swing components inside of them such as JMenuBar, JTable, JButtons, JProgressBar.
Model classes: The two models I have are TableModel (used by the TablePanelView to display the user's music library and which stores the path to the directories of his/her songs in a List ) and PlayerModel (used by the PlayerPanelView to manipulate the the digital audio files that the user selects i.e play/pause/stop songs, fast forward etc.) The PlayerModel uses the selected by the user song directory to initialize itself.
So, my question is how can I implement the Presenter so that the different views (which use different models) are being able to communicate and share information between each other? Should I have a single Presenter to which the views talk or have a presenter for every view? If it's possible to have a single presenter how can that be achieved? If I have one Presenter for the MenuBarView, TablePanelView and PlayerPanelView and those views are contained in another view (which is the MainFrameView ) should I combine the presenters in some way, and if yes how?
If i were you I would try the MVC (Model View Control) pattern before trying MVP. It´s very similar but I would say it´s a bit easier to understand.
I wouldn´t create a own view for the MenuBar because you probably won´t create it dynamically. Just write a method in your MainFrameView where you initialize it and call that in the constructor of the MainView.
The model is a property of the item you use. Now if you want to create a Panel with a own model but also want to access the model from the MainFrameView you simply write a Getter/Setter for it. It looks like this in the MainFrameView:
public TablePanelView tpv;
public void initTablePanelView(TablePanelModel tpm){
tpv = new TablePanelView();
tpv.setModel(tpm);
}
So you can use the public methods getModel() or setModel() that you wrote in the TablePanelView to access the Model.
I hope that helped.

how to implement MVC pattern for word guessing game?

I have some working code for the word guessing game. But I fear it does not confine the design rules especially the MVC pattern. The attached image is my GUI currently. I am throwing around objects from one class to another and I hear that it is a bad style. while I agree with that, I am not able to come up with good MVC pattern approach for the word guessing game or the Hangman commonly called.
The main application will have some like this:
public class Application {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
runApp();
}
});
}
public static void runApp() {
Model model = new Model();
View view = new View(model); //not sure if this correct, some suggest it is valid and some not
Controller controller = new Controller(view, model);
}
}
how would I approach this?
The GUI as seen in the attached picture would be the View Class. This includes all JButtons, Textfield, borders, labels etc. Attach actionlisteners to JButtons in the View class
The controller will pass the events to the model. for example, if some letter buttons are clicked, it would pass that letter "A" is clicked to model and the model will either send instructions to controller to update view or it will update view directly. from my understanding of the MVC pattern, the model class must be implemented and tested separately from view and controller. I do not understand how I can achieve this here. I have complete code available. I need to refactor to confine to MVC pattern. kindly pass on your suggestions.
I think one of the areas you are getting confused over is "responsibility". What is each component responsible for and what can it actually do.
The problem isn't that you are passing Objects around you program, but more that the objects you are passing are exposing parts of your application that the recipient has no business knowing about or should be allowed to manipulate.
What I mean by this is, if you were to pass the "buttons" panel to the "guess" panel, because you wanted to have the ability to allow the "guess" panel detect when a button was clicked, you've exposed the "buttons" panel to an area of your application that has no right to actually see it.
What's stopping the "guess" panel from removing components? Nothing...
Instead, we should use interfaces which determine what each part of the application can and can't do and what information is available to it.
This is where you model comes in. The model determines what information is available, how it can be accessed and what events might be triggered to notify interested parties that the model has changed.
For example. Your "buttons" panel would tell the model that the user has made another guess (in response to the user pressing the button). The model would then raise an event, which would notify the "guess" panel that a change has occurred. The "guess" panel then would update it's state accordingly, asking the model for the information it needed in order to represent the current state of the model (as far as it was responsible for).
You could take a look at
Code to Interface, Access by name and Instance Data
Program to an interface
Now, with the MCV pattern, the view must be able to see the model, the controller must be able to see the view and model and the model doesn't care.
The controller is listening for changes to the view (ie user interactions), which it passes to the model. The model fires notifications about changes to it's state and the view responds to those changes by updating itself as required.
For example, the use clicks a button on the "button" panel. The "button" panel's controller detects this event (probably via an ActionListener), it process this action and updates the model.
The model updates it's internal state and fires some kind of event.
The "guess" panel detects this change in the model (via some kind of listener) and updates it's view accordingly (update the guess's and the image as dictated by the model).
Now, remember, Swing doesn't use a pure MCV pattern, it's controls (ie buttons) are both the controller and the view, so just be careful when playing around with these...
I would start with a HangManModel interface which defines all the properties you want to expose, such as the guesses, the "secret" word and perhaps the number of incorrect guesses made and the state of the game (win or lose) for example.
I would also define the listeners that might be registered to the model, which describes the events that this model can generate. You could use a PropertyChangeListener or even a ChangeListener or define your own, based on your own needs, for example...
public interface HangManModel {
public void addGuess(char guess);
public char[] getGuesses();
public String getSecretWord();
public int getState(); // running, win or lose
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
Now this is just an example, personally, I might be tempered to hide the secret word and expose properties about it (like it's length for example). You could also be tempted to provide a setter for the secret word, so the model could be reset...
This would represent the "heart" of your application, around this, you would build your views and controllers.
EDIT : Working example of MVC (netbeans project, made by me) is download here or download here. Who does not know netbeans : in dist is executable .jar file and in src are sources.
It shows MVC pattern with two different views. On the left, you can left or right click to create circle or square and on the right you can see these squares and circles in table. You can change value (like size or position) of square or circle in table and it is updated into model which updates view so on the left you can see how that square or circle moved or resized.
You have good approach, but you got few things wrong. This is a basic, simple model of MVC :
As here you can see, the model DOES NOT send anything into the controller.
How to build MVC application? Mabye better start with the model. The model should have everything except the input/output handling. All the data, all the logic.
So you should have 3 main classes : Controller, View, Model.
For example you just create form with button which in each hit add one "A" letter into the middle of form.
In View class, you have update method, which paints and/or repaints the count of "A" letters into the form.
When you hit the button, it jumps into the method buttonClicked. This calls method on controller, saying that controller what just happend.
Controller see that and manipulates data in the model (in this example calls the method addA). After this, model should know that he was changed, so he call update method on the connected view class which repaints the count of "A" printed in the middle of form.
Addition
You can have multiple views for one model! We can add one more view, which in top-left corner of form prints the number of "A" used. Model can have list of view instead of just view and when changed, he just updates all of them.
Pseudocode
public class Application {
private Model model = new Model();
private Controller controller = new Controller();
private View view = new View();
public Application(){
model.registerView(view);
controller.registerModel(model);
view.registerController(controller);
}
}
Interestion question... So far I heard about MVP and MVVM design patterns used whithin desktop apps, but I have never seen MVC for this type of apps. However, I just took Spring MVC (the best java web framework) and tryed to apply it on desktop apps.
I would create a front controller that handles all events for the app.
This controller gets an event and sends it to EventResolver.
EventResolver returns back the name or something of a method and class which will play a "controller" role to the front controller.
After the front controller creates an instance of this class and calls a method.
In the method body you call some business logic and return model and id for ViewResolver to the front Controler.
6 Again the front controller analyzes the result and calls an approperiate ViewResolver.
Yes, this is how spring MVC works and I just copied it) But why not to use the best!
There's lots of different flavors of MVC, but they all share the same general idea.
The first thing to understand is exactly what the model is. The job of the model is to handle all the logical code. So in this case, the model will track which letters have been guessed, what the word to guess is, whether the game is over, and how many pieces of the stick man are showing.
Basically, you should be able to simulate the game in its entirety just from function calls into the model.
There's a few ways to pass information from the model to the view. The view could poll the model periodically to see if anything has updated. This method is not very elegant. A simple way that is often effective for small-scale projects is to pass a View object into the Model object and whenever anything changes in the model, refresh everything in the view. It's no big deal for a smaller UI to do this. Finally, you can create a Listener registration system (Observer pattern) to have specific parts of the View subscribe to specific events in the model. This method is what I've done for larger UI projects.
The controller's job is to pass user input to the model. For this reason, the controller and view can often be defined in the same classes. This is okay! It's much better to have your JButtons have a click method that calls the model directly rather than telling some Controller class to pass it on to the model.

GUI with multiple frames

I'm looking to build out a Java GUI with a table area and an area that will display the data of a selected row of the table. I've never tried a multi-frame set up before so before I venture to do this I wanted to check with others. Is it difficult to have two frames and have them passing data back and forth? The idea would be that I could move the details frame anywhere I like on the screen or to a second monitor and allow the table to go full-screen if the user wants. Any input or examples are appreciated.
don't to create two of more JFrames use JDialog instead,
reuse this JDialog for another action(s)
create one JFrame and one JDialog for displaying details
have to determine if and which of JTables row(s) is selected
better would be to set ListSelectionMode to the SingleSelection
maybe would be better to invoke (show that already exist) JDialog from JPopupMenu Action
You should have no problem in doing what you are after. You can have public methods in each frame which expose properties and/or structures and you then pass the instance of one JFrame to the other. This should allow you to pass data back and forth.
That being said however, I think that this scenario is valid only when you have one, two, or at most three JFrames. Having a lot of frames calling each other could result a maintenance nightmare.
there are several possibilities to do so:
you can add one of the jframes as a listener to anothe, or both to each other. For this, you have to implement a listener mechanism, like in java.awt. You can pass the information contained in the event objects - this would be the most clean alternative
you can pass the instance of the detailframe directly in the constructor of the main frame and call operations from main frame on detail frame. this is the simplest way, but you will need lot of code changes if you have some new features to add

Java: Getting values from GUI

In my application user gets to choose "distribution type" for a few parameters and then I create Graph and show it to him. There are 3 different types of these distributions with each of them having its own parameters ( like alpha, beta, probabilities, etc). Each parameter can have either of those distributions.
Here is the screenshot to make it clear, what I'm trying to describe:
Distribution options are contained in CardLayout, that is controlled by combobox.
When user presses the button, I need to instantiate proper domain objects for distributions. Right now, I'm just passing ComboBox item (which is enum) and CardLayouted panel to factory that chooses proper subpanel and instantiates correct object. But it seems wrong to pass around gui objects, also makes factory useless for any other situation.
But I can't think of a better way to instantiate correct object. Probably just one idea:
Let CardLayouted panel decide which panel is ontop and instantiate
proper object on request. I wouldnt need any factories for this one. But is it ok for gui object to do this kind of logic? How can I delegate to domain in a proper way?
All suggestions will be appreciated a lot!
Swing has generally good support for MVC and pushing or pulling data from a domain object to input / display controls. What I'd do is:
Instantiate the panels you put into the CardLayout with a "blank" domain object as its GUI model. (Or some sort of locator that can retrieve the model from another layer.) Then hook up change notifications on your input components that will update the domain object when the values in the input change.
Then, when it comes to persisting the domain object, just retrieve it from the form panel.
If you need to show the same model value in two controls, they should share the same model. If you need to do updates to an object being displayed from lower layers of the code, you should perform the update on the model instead of / in addition to the domain object.

Categories