I have a program that is basically set up just like the one in this MVC example: http://www.leepoint.net/notes-java/GUI/structure/40mvc.html
In my program there is a process which takes quite a bit of time which freezes my GUI. I want to GUI to continuously update while the process is running. To do this I believe I need to use a SwingWorker. I don't know where in my MVC pattern I should be invoking this SwingWorker.
My thinking is that I should be running it in the MultiplyListener actionlistener of the controller. Would this be correct?
In this case, the model is a mathematical operation that evolves over time, perhaps by iteration. Clearly, the worker belongs in the model, as shown here. The setProgress() method will notify any PropertyChangeListener, and process() can notify any other listening view, as shown here.
Addendum: In the second example, the worker updates a different model: the chart's dataset named collection. The chart, in turn, listens to the dataset and updates itself in response to the change.
In the example cited, the controller installs action listeners on behalf of the model and view. In this related example, the GUI action listeners are local to their respective views. In either case, Action would be a suitable choice for encapsulation. The model notifies its observers when its internal state changes in response to user initiated actions.
I think that your SwingWorker belongs in the Control and I'll tell you why. I feel that the Model should be as View agnostic as possible and should be created with the idea that it can be used with different views and controls, and even with a completely different GUI library, if desired. For instance, you are currently wanting to use the Model in a Swing GUI, but what if later you want to use it in an Android application? In order to allow it to be used with as few modifications as possible, most code that is Swing-specific, such as a SwingWorker should reside in the Control or View.
For example, please check out this answer.
Related
I'm writing checkers for android. And I faced a problem with organization human vs computer part of program architecture. It's known that the user interacts with the program through the GUI. GUI elements have listeners which are responsible for some events.
So, when it is human's move, we can use those listeners to do all what needed. But, when it is computer's move, we can't use listeners because there is no directly interaction with the GUI.
My question is: where is in program structure I can manage neccessary operations and, most importantly, subsequent interaction with the GUI to manage computer's move?
And can I use Service for this?
Documentation said:
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user..
So, Servise is more useful for background processes. But for my case, i think it's not suitable..
Anyway, thanks for help.
I would use an EventBus for that.
Each time a player (IA or human) do an action (for example move), you post a custom event with all informations you need to the EventBus.
In your GUI, that you've registered to the eventBus, you get the event and display what you want.
Don't know if it's stupid or reasonable question.
I have methods which returns float/int data (x,y,z positions) of the P5 Glove (if you know it).
I also have update method which responds to the glove pulling.
All i'm having trouble with is creating UI and presenting the data in text area, means every update the text areas presenting the data refreshed and present the data.
Since code isn't that short here are links to the class: Details presentation methods and update
let's say for now I want to present showActiveLedPosX() method which returns the X position as String.
the other classes are glove (using glove methods and creating glove object and UI).
Should I use different class for UI? or should I do it all on ShowGloveValues class
I've never created UI and therefore I'm kinda clueless here, Tried to read about it on numerous resource sites and still couldn't achieve what's needed.
1. Keep the UI thread apart from the Non-UI thread.
2. Event Dispatcher Thread is the UI thread, keep this thread to handle your UI only.
3. You can also use SwingWorker for this.
4. Swing is based on Mode View Controller. Moreover its better to divide your app packages also on the basis of MVC.
eg:
com.vivek.model; // Class responsible for Business Logic and Data
com.vivek.view; // Class responsible for the UI
I was developing a swing application which calls multiple methods & initializes different classes.
Also I have multiple threads in which they process intermediate results. My requirement is to display that intermediate data on some labels and text boxes on the fly.
Please help me which of the below approach is best in terms of memory and performance.
I can have setter methods for all my labels and text boxes. So that I can call these methods using that swing class object but in that case I need to pass the swing class object to every class wherever I want to set the data to labels.
Another way is I can create public static object of my swing class and I would call it from any class whenever I need to set the label text.
First method creates more overhead as I need to pass the my Swing class object to other classes.
Second method is easiest way but creating static objects might create confusion as this application contains threads.
I just want to know which one to go for and why?
Otherwise if anybody have worked on some complex swing app development - how did you manage these kind of issues?
This example is typical of your first approach in a multi-threaded context. For expedience, the model and view are tightly coupled: each worker thread receives a reference to the label it should update. The alternative is loose coupling: each view registers to listen to the model, which notifies all registered listeners using the observer pattern.
This simpler example uses both approaches:
Tight coupling: The worker obtains a reference to its target label in an enclosing scope.
Loose coupling: The enclosing view registers a PropertyChangeListener, which the model uses to signal the view via setProgress().
You'll need to decide which is important in your application. I agree with #JB Nizet's comment about the second approach.
Why dont you use the 2nd method with Singleton principle, where you can use the same single instance of the swing class, so there will be no use of using static , and its sometime confusing cause we are uncertain of the order in which the JVM loads the static members...
Think of a GUI as a model with a view. The GUI components make up the view, while you create model classes that represent the model. Changes to the values in the model are reflected in the view. The rest of the application interacts with the model, and not the view.
Here's one example from a Java Spirograph GUI that I did.
What is the best way to support two views over the same data, with both views allowing edits on the data, in presence of various listeners in the UI and the underlying model.
Example, simple approach is to bind JTable with an AbstractTableModel instance, and pass reference of AbstractTableModel instance to the other view as well.
But if the other view chooses to change the underlying abstract table model instance, and in presence of some other listeners, like table model listener and some listeners on the JTable, it gets complicated very quickly, at least for me.
Not entirely sure, but it should be possible for some combination of these objects to lead to events being raised inadvertently.
I am not aware of any patterns in swing that can help with this problem, but apparently MVC is not encouraged in Swing.
In the past, I would have chosen to ensure that only the model raises events, and that changes the view, called the passive view pattern.
Your thoughts? (Swing and application design newbie here.)
I would recommend to centralize your data in some sort of cache object in something like a list, because imagine you get more then just two views to display the same data, it can get kinda messy to carry your tablemodel all around.
So simply let your cachelist inform about your data changes (update, create, delete...) by an own implementation of propertychangelistener or just with an eventbus. All interested views can sign up at your cache for data changes and get informed automatically. So neither of the views need to know each other which keeps your code kinda simple and easy to maintain and expandable for other views.
You can totally deviate from the listening scheme and switch to an EventBus based scheme, I don't think it is hard to replicate in a Swing framework. It's a concept from the GWT framework. Your application should initialize an event bus and its reference must be passed to those "objects" which need to broadcast events. It should be a "singleton" class that passes around the same instance of the EventBus.
So the data modifiers in your model can "post" an event into the eventbus and any UI can wish to receive the broadcast. So a change in the model by one of your tables will broadcast an "update" event which is received by your other table, which inturn updates its display.
Design your callbacks well from the idea and you should be having a very simple and clean solution.
I'm working with a combobox in a Swing-based application, and I'm having a hard time figuring out what to do to differentiate between an ItemEvent that is generated from a user event vs one caused by the application.
For instance, Lets say I have a combobox, 'combo' and I'm listening for itemStateChanged events with my ItemListener, 'listener'. When either a user changes the selection to item 2 or I execute the line (pseudocode):
combo.setSelection(2)
.. it seems like I'm not able to tell these events apart.
That said, I'm no Swing expert by any means, so I thought I would ask.
Thanks!
Whether the user selects Item 2, or the API calls setSelection(2), the event will appear the same.
The solution to your problem might be in re-thinking what you want the itemStateChanged code to do when the selection changes. Why would your app work differently under each condition? Maybe there are similarities that you can use to your advantage.
Be careful when using flags. The itemStateChanged event will occur on the Event Dispatch Thread, which is a different thread than the one on which you'd set the state of the flag. This would mean that using a flag may not be 100% reliable.
The Action and Reaction law is quite clear :). If you try to react on change there is no need to distinguish between user and application. I can imagine only one use case where you need to "distinguish". The case where application is displaying some data. In this case you have, probably, data model for your application. And also there are some change listener in this model and application GUI will react by setting values to components. And also. If user selects anything into GUI component. The data model will react by changing value. In this case it is easy to set up some sort of read-only state on data model which will notify model to ignore ANY event coming from observed objects. This notification set should run in EDT and there is no problem with flagging. Small example:
class ApplicationDataModel {
private Flag current = Flag.RW;
public void setData(ApplicationData data) {
current = Flag.RO;
setDataImpl(data);
notifyObservers();
current = Flag.RW;
}
public void reaction(Event e) {
if (flag = Flag.RO) return;
...
}
}
Be careful with flagging and don't forget about threading. If you are calling setData from another thread then EDT you are going into trouble. Of course. The extraction of ApplicationData object has to be run in different thread ;). In general, rethink design of your application.
You can set a flag in your code before you set the selection, and then check for this flag in the listener (and unset the flag if it is set)...
There may be a better way since Java 6, but this is the way I always used to do it...
[Edit]: As David points out, you will need to set the flag (and update the combo) in the EDT using SwingUtilities.invokeLater or similar (you should do this anyway, as you are changing a UI control)
If you need to tell the events apart, then there is probably something about your design that needs a rethink. The whole point of MVC is to decouple changes to the model from the actual mouse clicks of the user.
Perhaps you should restate the question in terms of why you would ever want to differentiate between these two situations. We could then provide some guidance on a different way of achieving the goal.
So I'm guessing you want the user selection to perform some action rather than just a plain old direct state change. This is an issue caused by limited flexibility (flexibility is always going to be limited, particularly if you have flexibility in other directions).
My suggestion:
Firstly, always go straight to using model in Swing. The widgets are way to complicated and you want different concerns to be split up. Fortunately Swing is already there with its models.
A common pattern is to have delegation between models. So in this case you have the "real" default model that holds your data. Insert between the JComboBox and real ComboBoxModel and delegating ComboBoxModel that performs actions on state change instructions. Your application code should ignore the JComboBox and go straight for the real ComboBoxModel bypassing the delegating model. So in a diagram:
User -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- Application code