I know SO is for specific questions but I need an advise on what is the correct practice in Java for working with swing worker thread.
My application generates large HTML text in response to a calculation process which is is displayed in a jTextPane. To avoid blocking the GUI I used to do the calculation in a Swing Worker Thread.
My problem is the following to start the calculation I need plenty information available in different menus checkboxes and listbox of the GUI, and at the end of the calculation I need to start functions within the EDT.
Here are 2 possibilities for me :
First one is to send plenty of information to my Swing Worker and also need to pass the MainFrame to access specific functions in the "done()"
public class MyWorker extends SwingWorker<Void, Void> {
private MyMainFrame frame;
public MyWorker(plenty of params) {
}
#Override
public Void doInBackground() {
//my background process
}
#Override
public void done() {
frame.myfunc1;
frame.myfunc2;
frame.myfunc3;
}
}
Second one would be to use a Inner Class
Which one is correct to do in Java. If both are "correct" what are the pros and cons of one against the other.
Both approaches are OK. The advantage of an inner class is that it has access to the internals of the enclosing object. The disadvantage is that it's not reusable in another context (another frame which would have a similar interface, for example).
Just make sure your code is well structured and readable. For example, you might want to extract the three method calls in your done() method in a single method of the frame.
If it is the large amount of parameters you have to pass in the constructor that is bothering you, you can group those parameters in a container object and just pass the container (e.g. a MyWorkerContext class).
I personally would try to avoid passing the UI (elements) itself, but rather pass a model/stream/... which will be updated by the SwingWorker, allowing me to refactor the UI later on without having to fiddle with my SwingWorker class.
Related
I have a program that must output the data of a weighting scale. It uses a thread to read continually data from the rs232 source and must output the data graphically. The user can open and close as many Jframes as it wishes and all must show the same data that is read from the rs232 in a JTextArea. How can I approach this?
Thank you very much in advance.
There are a number of ways you might approach this problem
The user can open and close as many Jframes as it wishes and all must show the same data that is read from the rs232
This raises the question if you're only interested in the real time results or the historical results. For argument sake, I'm only going to focus on the real time results.
Basically you need to start with a class which is responsible for actually reading the data from the port. This class should do only two things:
Read the data
Generate events when new data is read
Why? Because then any additional functionality you want to implement (like writing the data to a database or caching the results for some reason) can be added later, simply by monitoring the events that are generated.
Next, you need to define a interface which describes the contract that observers will implement in order to be able to receive events
public interface ScaleDataSourceListener {
public void scaleDataUpdated(ScaleDataSourceEvent evt);
}
You could also add connection events (connect/disconnect) or other events which might be important, but I've kept it simple.
The ScaleDataSourceEvent would be a simple interface which described the data of the event
public interface ScaleDataSourceEvent {
public ScaleDataSource getSource();
public double data();
}
for example (I like interfaces, they describe the expected contract, define the responsibility and limit what other people can do when they receive an instance of an object implementing the interface, but that's me)
Your data source would then allow observers to register themselves to be notified about events generated by it...
public interface ScaleDataSource ... {
//...
public void addDataSourceListener(ScaleDataSourceListener listener);
public void removeDataSourceListener(ScaleDataSourceListener listener);
}
(I'm assuming the data source will be able to do other stuff, but I've left that up to you to fill in, again, I prefer interfaces where possible, that's not a design restriction on your part ;))
So, when data is read from the port, it would generate a new event and notify all the registered listeners.
Now, Swing is not thread safe, what this means is, you shouldn't make updates to the UI from any thread other then the Event Dispatching Thread.
In your case, probably the simplest solution would be to simply use SwingUtilities.invokeLater to move from the data sources thread context to the EDT.
Basically, this is a simple Observer Pattern
There are a lot of other considerations you need to think about as well. Ie, are the frames been opened within the same process as the data source, or does the data source operate within it's own, seperate process. This complicates the process, as you'll need some kind of IPC system, maybe using sockets, but the overriding design is the same.
What happens if the data source is reading data faster then you can generate events? You might need some kind of queue, where the data source simply dumps the data to the queue and you have some kind of dispatcher (on another thread) reading it and dispatching events.
There are number implementations of blocking queues which provide a level of thread safety, have a look through concurrency APIs for more details.
... as some ideas ;)
first, create a frame class extends JFrame, and create a method to receive data from rs232. Then every object of this class can get data using that method.
u can create one frame by creating one object of the class.
Helo guys!
I am new to JavaFX. I am writing really small application which simulates working of printer. Simulation is running on special thread called PrintingProcess (this process is doing only one thing - waits given time and then increment counter). I need to send this value to window, where labels should show how many pages was "printed". Is any way to do it? So far I wrote small singleton class to hold value.
[edit] I solved it using tasks :) thanks for help
You should use the Task.updateProgress method. Call it to specify the current percentage of pages printed. Override Task.call to perform the action which needs to run in another thread. This method should never manipulate a JavaFX component. You can then oerride methods such as Task.succeeded to implement the behaviour of your UI when the print job is over. Look at the doc of this class to fully take advantage of it.
Platform.runLater(new Runnable() {
#Override public void run() {
textLabel.setText(yourValue);
}
});
The example above is quite simple. You ask JavaFX a runnable as soon as it can. I don't know how that works exactly but that's the way to change UI components from a non-JavaFX thread.
You could pass textLabel variable to any thread with a custom class or a new anonymous thread.
EDIT:
I find Dici's answer more appropriate for your application. I wouldn't recommend putting this code in any loop incase you may still use this.
My project is built upon Java's Swing library. It spawns the EDT which displays my GUI (which works correctly).
The entrance to the program, which initializes the EDT:
public final class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Start());
}
class Start implements Runnable {
private Model model = new Model();
private Controller controller = new Controller(model);
private View view = new View(controller);
#Override
public void run() {
// Initialize the view and display its JFrame...
}
}
}
}
However, when a button / radio box / etc. is clicked within my GUI, the Controller class must perform an action on the model.
My questions are the following:
Should I wrap the controller's code in a new SwingWorker?
If no, should I wrap my model's code in a new SwingWorker?
If I wrap the controller's code with threads, do I need to synchronize the shared state variables within my model?
If my model, running on a new thread, notifies my GUI of changes, will this occur on the EDT or on the new thread?
For example:
public class Controller {
public void updateModel() {
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
model.somethingSomethingSomething();
}
}.execute();
}
}
public class Model {
public void somethingSomethingSomething() {
notifyListeners(); // This is going to notify whichever GUI
// is listening to the model.
// Does it have to be wrapped with Swing.invokeLater?
}
}
public class View {
// This function is called when the model notifies its listeners.
public void modelChangedNotifier() {
button.setText("THE MODEL HAS CHANGED"); // Does this occur on the EDT?
}
}
Instead of updating your model from doInBackground(), publish() interim results and update your model from process(), which executes on the EDT. In this example, JTable corresponds to your View and TableModel corresponds to your Model. Note that JTable listens to its own TableModel.
You can read about it here: Improve Application Performance With SwingWorker in Java SE 6. In short: all time consuming operations, which are not affected UI must be done in another thread. To show results of operation you must go back to EDT. For example, if you make database search, you should show a progress bar (usually infinite) and start the search using SwingWorker. To show search results in a table, you must be in EDT. Alternatively you can use foxtrot lib (it allows to make your code more Swing convenient without to redesign it).
If your controller code permanently updates the swing widgets you should execute it in EDT or at least perform these updates of UI in EDT (using SwingUtilities.invokeLater, chunk processing in SwingWorker or swing.Timer).
So your sample is wrong: model update should be up-to-date in EDT.
One alternative approach, from Java Concurrency in Practice 9.4.2, uses a "Split" or a "Shared Data Model". You update your Business Model on whatever thread you want, likely the long-running non-EDT thread. But then, instead of directly calling notifyListeners() and worrying about which thread you are on, simply call myComponent.repaint(), which will queue up a repaint request on the EDT.
Then, somewhere in your paintComponent() method, you explicitly grab all new data from the Model, typically in a method called modelToView()
commentTextArea.setText(myModel.getCommentText());
fooLabel.setText(myModel.getFooText());
...
The upsides are that threading is not an issue, and, at least to some minds, this "makes sense", and the model is nicely decoupled from the view. A downside is that you are resetting all the values every time. So if you have 100 JComponents, that's 100 things getting set. Also, the view is pretty tightly coupled to the model.
Working Code Examples
#MadProgrammer and #kleopatra are correct that, if the view directly contains the components that are being updated, you get an "infinite loop of doom". For proof, see
Demo_14716901_Fails
However, if the view is isolated from the components, you avoid the infinite loop. Normally, the higher level view would contain stuff like JSplitPanes, holding JScrollPanes, holding Boxes or more JPanels, holding the actual low level components. So this requirement, IMO, is not unreasonable.
Working code at Demo_14716901_Works
Some Comments Added for the Downvoters:
Some people want to defeat Swing. They are writing instrument control code or algorithms and just want to get their job done without worrying about the EDT, endless SwingWorkers and invokeLaters. This technique lets them get their job done. With the one important caveat noted, it works. (Personally, I understand and generally like Swing, but many don't).
While Swing components are nicely MVC, they are generally at far too micro a level. The "real" model is not a single String, it is dozens of values. The "real" view is not a single JLabel, it is many JPanels, each with many components, combined with scrollers, splitters, etc. This technique usually fits the real world better, allowing the programmer to think naturally at a higher level.
As far as "bad practice", take it up with Brian Goetz, Josh Bloch, etc. o.k., that's "appeal to authority", but it works for me. :-)
I have a simple Android app which uses AsyncTasks for I/O. A frequent pattern:
User clicks a button
In response, an onClick handler instantiates and .execute()s an AsyncTask
Once the AsyncTask completes, the UI should be updated in some way
According to the documentation for AsyncTask, the correct way to accomplish the UI updates is to override onPostExecute in the AsyncTask class - this will be invoked back on the UI thread after execution and thus can touch the widgets, etc.
However, it seems wrong to me that onPostExecute should have any sort of hard reference to a UI element. I would prefer to keep my I/O tasks and UI code separate. Instead, this seems the obvious situation where I should pass an opaque callback to the AsyncTask - the callback retains a reference to the UI elements and thus we maintain isolation and reusability in the code. A classic delegate pattern (or perhaps listener, event, etc, many options here).
As an example, the code below seems wrong to me:
class QueryJobsDBTask extends AsyncTask<Void, Void, ArrayList<ContentValues>> {
#Override
protected void onPostExecute(ArrayList<ContentValues> freshJobsData) {
someList.clear();
someList.addAll(freshJobsData);
// BUG why does my DB query class hold UI references?
someAdapter.notifyDataSetChanged();
}
After some research, it looks like the Handler class is the most straightforward and lightweight way to accomplish a delegate pattern here. I can write reusable AsyncTasks for I/O and specify contextual UI update callbacks on a per-instance basis via Handler instances. So I have implemented this new Handler-enabled base class
public abstract class HandlerAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Handler preExecuteHandler, postExecuteHandler;
public void setPreExecuteHandler(Handler preExecuteHandler) {
this.preExecuteHandler = preExecuteHandler;
}
public void setPostExecuteHandler(Handler postExecuteHandler) {
this.postExecuteHandler = postExecuteHandler;
}
#Override
protected void onPreExecute() {
if (preExecuteHandler != null) {
preExecuteHandler.sendMessage(Message.obtain());
}
}
#Override
protected void onPostExecute(Result result) {
if (postExecuteHandler != null) {
Message msg = Message.obtain();
msg.obj = result;
postExecuteHandler.sendMessage(msg);
}
}
}
And voila, all of my I/O tasks are now properly partitioned from the UI - and I can still specify simple UI update callbacks when needed via Handler instances. This seems straightforward, flexible, and superior to me ... so of course I wonder what I'm missing.
How is the current framework solution superior? Is there some major pitfall to this approach? To my knowledge the topology of code execution and threads is the exact same at runtime, just code coupling is looser (and a few extra frames on the stack).
This is an elegant solution for segregating UI/Background tasks in small projects, although passing Runnables is even more elegant. Keep in mind that the AsyncTask is a wrapper around Thread/Handler, so you're doubling up on the thread-messaging that's already going on behind the scenes. The flaw here is that if you design the AsyncTasks to be reusable, you'll need to make sure that the IO you're running are all thread-safe, as there's no communication between the various AsyncTasks as to who is active or accessing which resources. An IntentService might be more appropriate if you need to queue background tasks rather than just fire them.
It's not so much a matter of superiority as purpose & use-case. AsyncTasks are usually written as private classes (or declared anonymously inline) within Activities, and as such inherit the Activity's references to various UI elements that need updating anyway.
If an AsyncTask is of sufficient size and/or complexity that it should be pulled out into its own class, and can be re-used by other classes, than using Handlers for better decoupling is a great idea. It's just that it's often not necessary, as the AsyncTask is accomplishing something specific to the Activity in which it was defined, and for simple ones, the corresponding handler code could even be larger than the entire AsyncTask itself.
As part of a larger application, I am writing a settings class, which collects and stores user-defined settings. This class is a singleton, and is instantiated during application startup.
In order to accept user input, two different GUI frames are insantiated from within ConfigSettings.java, from a public static method, selectSettings(). Both are subclasses of JFrame. Here is the code for the instantiation of the file selection dialog:
private void selectFile() {
SelectFileGUI fileSelector = new SelectFileGUI();
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
}
This works fine when the application is initially run. However, at a later point the user may alter their selected settings, including selecting a new source file. This is done by calling selectSettings() again.
The issue I'm having is that any subsequent attempt to instantiate and display these GUI components again results in a new JFrame being displayed, but with a grey background, and no buttons or other components shown. While debugging I was also failing to create new instances of SelectFileGUI directly.
What could be causing this sort of behaviour?
I would check to see if the second time you call it you are using the GUI thread or calling from one of your own threads.
At the top of that method you can test for it (The AWT thread is pretty easily identifiable by name) and have it throw an exception so developers know not to call it on the wrong thread--or you can block their thread and do it in a worker thread.
I don't know what is causing this behavior but in your code the following simply cannot possibly be the right way to manage dialogs (more below):
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
Do you want your dialogs to be modal or not?
If you want them to be modal, then you simply make a blocking call like when you're invoking JColorChooser.showDialog(...) method and your return "value" is your color/file/whatever.
If you want them non-modal, then you use a callback to get your color/file. In the JColorChooser dialog example, you'd call the createDialog(...) method and use the ok/cancel listeners as callbacks.
I suggest you take a look at sun's tutorial, for example the one on color chooser, to see how to correctly display a modal (or non-modal) dialog:
http://java.sun.com/docs/books/tutorial/uiswing/components/colorchooser.html
Once again, that synchronized(this) { try { wait() ... } to manage something as simple as a file selector/dialog frame just cannot be correct.
Agree with BillK: sounds like you're calling it from outside the EDT first time around (so your call to wait() doesn't block the EDT), then from the EDT the second time around. See SwingUtilities.invokeAndWait() and/or Dialog.setModal().
The consensus here is that you are breaking the rules governing the use of the AWT painting thread (the Event Dispatch Thread).
A couple things to note:
If your code attempts to paint your GUI components outside this painting thread, the gray dialog could be the result of a deadlock between the EDT and the thread your application is using to paint.
If you do get into this situation, you will experience the inability to create new dialogs as described.
However, as you mention that you are debugging while experiencing this problem, it might be that you have paused the EDT through your IDE.
Take a look at this tutorial for some guidelines on how use threads in a client application.
To fully appreciate the issue, it would be nice to see some more code - pertinent parts of selectSettings(), for example.