Is there a way to block the execution on the EDT, with still having a vivid gui?
I noticed that JDialog/JOptionPane has something similar, when calling setVisible(true).
Why would i need this?
My Class should satisfy to following interface:
interface Quitable {
boolean quit();
}
My Class needs a implementation like this:
class MyApp implements Quitable {
ExecutorService executor = Executors.newCachedThreadPool();
// ...
public boolean quit() {
FuturTask<Boolean> futureTask = new FutureTask<Boolean>(saveJob);
executor.execute(futureTask);
// TODO: keep gui vivid
boolean saveResult = futureTask.get();
return saveResult;
}
// ...
}
I need to return the result of the save process (which may take some time and may fail). Or would you suggest another solution? Thanks for any ideas. ;)
Dialog causes the an event loop to be executed whilst it is blocking. There is a filter that allows certain events through such as repaint requests, invocation events and events to the dialog window. The API for this is not exposed.
There was a library (Foxtrot, IIRC), that used a hack on Dialog to expose this behaviour.
I would strongly suggest structuring your program in such a way that this is not required. It's a very procedural rather than event-driven organisation. So queue your task on another thread (possible a thread pool/executor service or GUI-like event-loop), and then update the GUI with java.awt.EventQueue.invokeLater.
JDialog does not block the execution of EDT, EDT ignores events except jDialog's event when it is opened as modal.
I do suggest you to show progressbar as modal, before calling quit method.
Related
I'm attempting to add a fancy InfiniteProgressPanel as a GlassPane for my big Swing program. However, it does not appear. It looks similar to this:
...
InfiniteProgressPanel glassPane = new InfiniteProgressPanel();
setGlassPane(glassPane);
...
glassPane.start();
doSomeStuff();
glassPane.stop();
...
I believe it is running in the same thread as the long process it is meant to cover up. I'll admit, I don't know nearly enough about threads, and I should probably figure out how to run that InfiniteProgressPanel GlassPane in a separate thread, and the long process in its own thread, too.
Be sure to:
Run all long running code in a background thread. This is a must.
Sounds great! How do I do so? Encapsulate all of the long-running code inside of an .invokeLater method? And should that be SwingUtilities.invokeLater or EventQueue.invokeLater? And what's the difference, anyway?
No, by using SwingUtilities.invokeLater(new MyRunnable) you're doing exactly the opposite -- you're guaranteeing that the long-running code will be called on the Swing event thread -- the exact opposite of what you want. Instead use a SwingWorker's doInBackground() method to run the long-running code. Regarding your second point, there's no difference whatsoever between SwingUtilities.invokeLater and EventQueue.invokeLater.
Make most all Swing calls on the Swing event thread, also a must.
Fantastic! Again, how do I do so? Same thing as above?
By using SwingUtilities.invokeLater(new MyRunnable) as noted above, or if you're using a SwingWorker then use its publish/process method pair as the SwingWorker tutorial will show you.
Call setVisible(true) on your glass pane since per the JRootPane API, all glasspanes are by default invisible.
Romain Guy's InfiniteProgressPanel doesn't seem to need a setVisible(true). It appears when the InfiniteProgressPanel.start() method is called.
I am not familiar with this, do you have a link?
Threads are different processes in the same program, per se.
In java, there are many different thread types, and the one you need for this job is SwingWorker.
The definition/use of this, from Oracle's docs, is:
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.
As you can see, this is what you need; a background thread.
final InfiniteProgressPanel glassPane;
...
class GlassPaneHandler extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
glassPane.start();
return setUpPaneAndStuff();
}
#Override
protected void done() {
try {
glassPane.stop();
} catch (Exception e) { } //ignore
}
private void setUpPaneAndStuff() {
//code
}
}
...
(new GlassPaneHandler()).execute(); //place this in your code where you want to initiate the pane
for more see:http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
When you are updating a swing UI you need to do it in Swing's Event Thread. This includes creation of components or any sort of progress updates. You can do this via the SwingUtilities.invokeLater(Runnable) method.
Therefore, you should create the glasspane and show it via the invokeLater if in a background thread. Any progress updates to the glasspane from your long running process thread should be done via the invokeLater.
Im going through concurrency documentation and I can't quite understand what they mean with:
In an applet, the GUI-creation task must be launched from the init method using invokeAndWait; otherwise, init may return before the GUI is created, which may cause problems for a web browser launching an applet. In any other kind of program, scheduling the GUI-creation task is usually the last thing the initial thread does, so it doesn't matter whether it uses invokeLater or invokeAndWait.'
-What is the problem with the init being returned before GUI-creation?
-Why is the GUI-creation usually the last thing a thread does?
Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.'
-How can you make it finish faster?
http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TumbleItemProject/src/components/TumbleItem.java
-Where is the EDT in the above example?
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
#Override
public ImageIcon[] doInBackground() {
final ImageIcon[] innerImgs = new ImageIcon[nimgs];
for (int i = 0; i < nimgs; i++) {
innerImgs[i] = loadImage(i+1);
}
return innerImgs;
}
#Override
public void done() {
//Remove the "Loading images" label.
animator.removeAll();
loopslot = -1;
try {
imgs = get();
} catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
-Why is initialisation of 'worker' here followed by the overwriting of several methods instead of just ';'? I have never seen this kind of notation before...
-Are all methods that aren't the 'doInBackGround()' method ,executed under the event dispatch thread?
'All concrete subclasses of SwingWorker implement doInBackground; implementation of done is optional.'
-In the code example ,I don't see a subclass for SwingWorker , unless new SwingWorker <>() , counts as a subclass?
'Be careful when invoking either overload of get from the event dispatch thread; until get returns, no GUI events are being processed, and the GUI is "frozen". Don't invoke get without arguments unless you are confident that the background task is complete or close to completion.'
-How would you use get() in a non-EDT way ?
My apologies if some questions are obvious and thank you for your time!
What is the problem with the init being returned before GUI-creation? -Why is the GUI-creation usually the last thing a thread does?
It says it right there in the text. "It might cause problems for browsers". It may be because the caller of init requires the method to create a GUI and schedule it for gui messages, and if none is created the caller fails.
How can you make it finish faster?
It's not about making the threads run faster, it's rather that if you have a long-going task, do it in a background thread instead of the event (GUI) thread as to not make it freeze.
Where is the EDT in the above example?
It's nowhere.. The applet has a EDT which is used when you for instance click a button or interact with the applet in other ways. I don't really understand your question here.
Why is initialisation of 'worker' here followed by the overwriting of several methods instead of just ';'? I have never seen this kind of notation before... -Are all methods that aren't the 'doInBackGround()' method ,executed under the event dispatch thread?
It's an anonymous class declaration of the SwitchWorker class. No, the doInBackground does not execute on the EDT, it's performed in the background. done is however scheduled on the EDT. See http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html for reference.
In the code example ,I don't see a subclass for SwingWorker , unless new SwingWorker <>() , counts as a subclass?
It does.
How would you use get() in a non-EDT way ?
As the documentation specifies:
get()
Waits if necessary for the computation to complete, and then retrieves its result.
So you should not call it until the background method completes, as to avoid freezing of the GUI.
I am building a java application and i have implemented custom listeners and events. The problem now is that there are many events and listeners and the application GUI thread is being blocked while the listeners process the events. Can this be solved using event dispatch thread? If so how?
The code for listeners:
public class ProjectChangeObserver
{
private List<ProjectChangeListener> listeners = new ArrayList<ProjectChangeListener>();
public void addProjectChangeListener(ProjectChangeListener l)
{
listeners.add(l);
}
public void removeProjectChangeListener(ProjectChangeListener l)
{
listeners.remove(l);
}
public void removeAllProjectChangeListeners()
{
listeners.clear();
}
public void fireProjectChange(ProjectChangeEvent e)
{
if(listeners.size() > 0)
{
ArrayList<ProjectChangeListener> safeCopy = new ArrayList<ProjectChangeListener>(listeners);
for (ProjectChangeListener cl : safeCopy ) {
cl.onProjectChange(e);
}
}
}
}
One of the features of Swing is that it is single-threaded.
However, there is nothing stopping you from spawning your own threads to do background processing. As long as you only make calls to revalidate() or repaint() then all the drawing will still be handled in the Swing thread.
(Remember that if you are going to be spawning other threads to do background work then ensure that your variables are declared volatile if you expect the Swing thread to see the same values as in your threads. Or pass the information back through another listener.)
If you are intending to do the painting itself (e.g. of custom components) in separate threads, then it is either not possible or very strongly discouraged depending on the situation. (Some exotic situations may permit multi-CPU generation of a scene in a custom thread-safe buffering class, but you're unlikely to be doing that).
If you are finding that your Listeners are CPU/network intensive, then you might want to think about the architecture of who is doing the majority of the shouting and who is doing the listening. I always try to minimise the amount of shouting in my "view" code so that it simply responds to events.
Incidentally, I've found Project Lombok and its Beta sister Lombok PG to greatly reduce the boilerplate of implementing the Listener pattern with #ListenerSupport.
Quite to the contrary, this must be solved avoiding the Event Dispatch Thread ("GUI thread" is just another name for the same thing). You must use SwingWorker to start an asynchronous task in its own thread.
You should run separate threads for your events if you want to prevent UI blocking.
If you want to use a single thread for events then you can create the thread and you can pass commands to your event thread using a queue where you store your events.
But you should open async threads for your events if possible and you should make sure you refresh the UI whenever needed.
I am using an API in a Java library which is called from the event dispatch thread and requires me to return a fully-initialized UI component. It looks like this:
public JDialog createDialog();
But I can only populate the dialog after loading from a database, which can take 10 seconds sometimes. Normally I would do that in a background thread but since this method is called from the EDT and since I have to return the dialog, that won't work. It's a third-party library so I can't change the method, but is there anything I can do to avoid blocking the EDT?
"Initialized" is not necessarily the same thing as "Populated". "Initialized" usually means that the object has been fully constructed, but may not have any data. "Populated" of course means that the data is present and any data-fetching tasks are complete. So it is possible to give your third-party library a fully initialized JDialog without any data at all.
The way I always like to solve this problem is to create a custom JDialog which displays a busy message or a progress bar or the like, and then request the data in another thread. When the data is returned, I replace the busy message with the data(On the EDT!). As to how you should perform your request in a background thread, I recommend using SwingWorkers. I like to use a private SwingWorker inside my custom JDialog which handles the request in the doInBackground() method, and handles the Display-related tasks in the done() method. Doing it this way will ensure that display-related tasks only occur on the EDT, and database-related tasks only occur OFF the EDT. If you'd like a reasonably good introduction to using SwingWorkers, check out Sun's tutorial on worker threads. A simple example would be:
public class DBDIalog extends JDialog{
private JLabel busyLabel = new JLabel("Fetching data from DataBase");
public DBDialog(){
//do your initialization stuff here
}
private class DBFetcher extends SwingWorker<Void,DBInfo>{
#Override
protected DBInfo doInBackground() throws Exception{
return fetchDataFromDB(); //or whatever database call to make
}
#Override
protected void done(){
try{
DBInfo info = get();
//replace your busy label with your DBInfo
}catch(InterruptedException e){
//do appropriate thread interrupted stuff
}catch(ExecutionException e){
//do appropriate general error handling stuff
}
}
}
}
A few things to remember, though: the done() method is NOT abstract, so you aren't required to override it. You should, though. If your doInBackground() implementation throws an exception, that exception will be swallowed unless done() has been overridden. Also, don't make changes to your GUI from inside the doInBackground(), unless you use SwingUtilities.invokeLater(Runnable), as doInBackground() is executed from a different thread than the EDT and making GUI changes from a background thread is asking for strange and inexplicable bugs.
When should this be used? Unlike other programming tasks, the point at which something takes too long to respond is a lot shorter in GUIs--The number I've usually seen written down is about 250ms. If your task takes longer than that, it should be in a background thread. In your case, 10 seconds should definitely be in a background thread, but then you already knew that :)
EDIT:
Seeing your comment, I see that most of my post is pretty moot. However, you can still use a SwingWorker:
Have your SwingWorker perform the data-retrieval, and in the done() method, have it construct the JDialog from the data and hand that dialog to your third-party library.
Construct the dialog without data, and then start a task to populate it.
From a user-experience perspective, anything that takes 10 seconds from initiation to completion is going to be an issue. It's best if you should them something right away, even if it's not in final form. If necessary, you could pop a modal dialog that simply says "Loading."
For what I can read, it is used to dispatch a new thread in a swing app to perform some "background" work, but what's the benefit from using this rather than a "normal" thread?
Is not the same using a new Thread and when it finish invoke some GUI method using SwingUtilities.invokeLater?...
What am I missing here?
http://en.wikipedia.org/wiki/SwingWorker
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html
Yes, you can accomplish what a SwingWorker does with vanilla threads + invokeLater. SwingWorker provides a predictable, integrated way to accomplish tasks on a background thread and report result on the EDT. SwingWorker additionally adds support for intermediate results. Again, you can do all of this yourself but sometimes it's easy to use the integrated and predictable solution especially when it comes to concurrency.
A code example:
import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx
// another one is built in
// since JDK 1.6 AFAIK?
public class SwingWorkerTest {
public static void main( String[] args ) {
/**
* First method
*/
new Thread() {
public void run() {
/** Do work that would freeze GUI here */
final Object result = new Object();
java.awt.EventQueue.invokeLater( new Runnable() {
public void run() {
/** Update GUI here */
}
} );
}
}.start();
/**
* Second method
*/
new SwingWorker< Object , Object >() {
protected Object doInBackground() throws Exception {
/** Do work that would freeze GUI here */
return null;
}
protected void done() {
try {
Object result = get();
/** Update GUI here */
}
catch ( Exception ex ) {
ex.printStackTrace();
if ( ex instanceof java.lang.InterruptedException )
return;
}
}
}.execute();
}
}
The choice always depends on personal preference and use case.
The second method has an advantage when refactoring. You can more easily convert the anonymous class to an inner class when the method it's used in is too large.
My personal preference goes to the second, for we have built a framework where SwingWorkers can be added and are executed one after the other...
SwingWorker is an implementation of a common pattern (in .Net i read there is GuiWorker BackgroundWorker for this), where you have to do some work in a GUI program, but keep the GUI responsive. The problem is that often GUI libraries are not multi thread safe, so the common way to implement such workers is to use the message loop of the library to transfer messages into the event loop of the application.
These classes allow you to easily update your GUI. Usually, they have a update(int status) method that is called by the thread, dispatched by the class, and handled by the GUI, while the thread continues its work.
Using normal threads, you would need to code your own events or some other messaging mechanism for this task, which can be a pain if you need this functionality often. Using invokeLater in Java for example, you would intermix the code for updating the gui into the code for doing the work. The SwingWorker allows you to keep things separate.
to answer your question, you are not missing anything. this class is just a convenient utility for wrapping up the functionality you discribed (start another thread to do the background work and then invoking some final action on the EDT with the results).
When working with Swing, it is important to know that the main swing processing (ie. rendering) happens on a single thread (which is not your main thread). This is often called the Swing or awt event thread. Those familiar with the JDK pre 1.6 will remember the "grey rectangle" bug if you spent too much time in an event dispatcher for a swing component. What does this mean. In any swing application you will have 2 threads running that you will now have to deal with. Normally if all your operations within an event dispatcher (the code that gets fired say when a button is clicked) is short (ie. changing the state of a siwng button) you can just run this inside of the event dispatcher. If your application is going to call a web service or a database, or you application state is driven by external events (ie. jms) or you want to just make your UI more interactive (ie. build a list of items and be able to do something else) you should use a thread other than the awt event thread (the main swing one). So in these cases you spawn a new thread and do what you have to, and when the results finally come back, you then somehow have to create an event that can be executed by the awt/swing dispatcher. SwingWorker is a great little design pattern that allows you do to do this (the other way is SwingUtilities). It is particularly useful for doing fetch data from external sources or say long calculations (rendering a graphics scene). It helps automate the dispatch and subsequent re-integration of the results from an external thread (other than the awt thread). For async events (ie. an event from JMS needs to update a result, use SwingUtilities).
SwingWorker makes trivial example code much more concise. However it creates a ball of mud. Communications to and from the GUI and executed logic are all welded together. So, I'd not like to see it used in real production code.
SwingWorker is far easier than mucking with your own threads because it gives you two things that are painful to manually, thread coordination between the UI and the background process and doing loops effective, background work that keeps working and sending updates back to the UI incrementally, like process a large amount of data, or loading a large list. The disadvantage (or advantage) depends on how you look at it, is that it hides the underlying implementation, so future version may have different behavior, performance, etc, which may be undesirable. I've found it quite useful as the glue between a UI event and my own command code, the SwingWorker maintains the link to the UI and my code pumps data.