Hey.. i have a program that check-in some people.. if they have a dept, the prog will show a panel with a list..
so i wanna to set the panel not visible after a few seconds.. how could i do that?
I created a new Thread (FadeThread) and started it in the view, but now, when i write
Thread.sleep(5000)
the whole program sleeps for this 5seconds,.. i only want to wait in the background for 5seconds and set the panel visible(false) but the whole UI and the program sleeps..
Thanks...
Thread.sleep() will suspend the current thread, which I presume is the event dispatcher thread in your case. If you do it in a background thread, it should work, although if you accidentally call run() instead of start(), it won't.
To execute code with a set delay, you'll have to use the Timer class. Much cleaner and you don't have to worry about accidentally creating too many threads, not exiting a thread properly and so on.
You are causing the Event Dispatch Thread to sleep so the GUI can't react to events.
Read the section from the Swing tutorial on Concurrency for more information and a potential solution.
Assuming you're using Swing, have a look at the SwingWorker class. You can create a process that will block for 5 seconds and then hide the panel in a thread-safe manner.
Alternatively you could used a ScheduledExecutor as long as you make sure you run it on the EDT using invokeLater().
Related
In my application I have a main frame window GUI, that launches a task in an executor service.
The submitted task generates output and stores in a file on Disk.
As soon as the o/p is generated GUI (observer) is informed of the o/p generated.
Here the problem is I am keeping a wait loop inside the main frame and as soon as a notification is received, the main panel is repainted on the main frame.
For small tasks this works fine, but as the size of the threaded task increases. The wait loop time increases and the GUI main window turns black till computations are done.
Can you please help me in correcting the design. Also How can a SwingWorker thread help in this case.
The wait loop time increases and the GUI main window turns black till computations are done.
Then you long running task is executing on the Event Dispatch Thread (EDT) which prevents the GUI from repainting itself. You need to execute the long running task in a separate Thread. A SwingWorker is a separate Thread which has an API that also allows you to execute code on the EDT as required, for example when the code finishes executing or when you have intermediate results.
Read the section from the Swing tutorial on Concurrency for more information. You can always search the forums for example of using a SwingWorker.
1)
Wait loops are the bane of all that is GUI. They are OK in other threads you have spawned, tricky in Executors (as they sometimes have limits on number of Threads, depending on which you use), and are completely out of the question on the EDT. That is the reason for your "blackscreen"
2)
Instead of using a custom (I assume it's custom) signal protocol and a wait loop, you could use one of the utility classes in Swing. For example, SwingUtilities has a couple of nice methods - invokeLater and invokeAndWait that take a Runnable and execute it on the EDT as soon as they can. Using this instead of the signal you have will allow you to not block the EDT and make your GUI responsive.
3)
If you really want to use a SwingWorkeryou may want to look through the documentation for it. It is essentially a way to do background tasks and report progress or completion/result to the EDT. Currently it uses an ExecutorService with 2 background threads, so having a lot of long running tasks on them is not a good idea (they will block each other). When creating a SwingWorker you would specify the method to be ran in the background, the method to be ran on the EDT when intermediate results are available, and the method to be ran on the EDT when you're finished either successfully or in error.
4)
This does not pertain to the question at hand, but if you ever get into a situation where you need a wait loop in the EDT and cannot avoid it using another design or technique, you can always switch to using a Timer. It can be setup to be called every x milliseconds without blocking the EDT and turned off once you are satisfied with some condition.
I had a program I got some help from here(how do I make my program check the stock market value every hour[java]) and I have been reading about swing worker ever since. I still have not fixed the program as I reread the official doc like 3 times and I am still a bit confused. Here is what I think I understand and please correct me if I am wrong.
You use SwingWorker when you have a long background process, and you put the SwingWorker inside your action performed? Once you create your process if you want it to update the GUI you make it return a value and you get() the value from the SwingWorker done() method. I am confused "where" to initialize SwingWorker because I want to say its the action performed, but isn't that where SwingInvokeLater is involved? if that is the case than what is the difference between the two. I believe SwingInvokeLater and done() both update your GUI by being run on the EDT.
I feel lost just writing that all out, I feel like I am getting closer to understanding but for some reason it just wont click. I don't like the examples the official doc provides, I guess I just don't see the whole picture. The official doc said to initialize your GUI inside a SwingInvokeLater but I don't understand the difference between that and just initializing my GUI in main().
Your questions / my replies:
You use SwingWorker when you have a long background process, and you put the SwingWorker inside your action performed?
It can go inside of an ActionListener, yes. You create it and execute it where it is needed, no more, and no less.
Once you create your process if you want it to update the GUI you make it return a value and you get() the value from the SwingWorker done() method.
That's one way to update the GUI. You can also use the publish/process method pair to update the GUI with interim results. You can also use a PropertyChangeListener attached to a SwingWorker to update the GUI. No matter what, it's usually a good idea to call get() somewhere, even if nothing is returned, as this will allow your Swing GUI to become aware of any exceptions that might have been thrown during the running of your SwingWorker.
I am confused "where" to initialize SwingWorker because I want to say its the action performed, but isn't that where SwingInvokeLater is involved?
The SwingUtilities.invokeLater(...) is used to queue code onto the Swing event thread, the EDT. This is not necessary inside of an ActionListener because its code is already called on the Swing event thread.
if that is the case than what is the difference between the two.
They are completely different. Again, invokeLater(...) is to call code on the event thread, and a SwingWorker is for calling long-running code off of the event thread.
I believe SwingInvokeLater and done() both update your GUI by being run on the EDT.
Yes they both can.
The official doc said to initialize your GUI inside a SwingInvokeLater but I don't understand the difference between that and just initializing my GUI in main().
By using SwingUtilities.invokeLater(...) you guarantee that the code passed into it is run on the EDT, the Event Dispatch Thread. If you don't do this, you don't have this guarantee. While many Swing programs will run most of the time without doing this, they may (and do) sometimes fail if this care isn't taken.
Edit
So I guess I am heading in the right direction. If I have a process that checks a value every hour on a website, since its a short process(takes a second) will it be better to use invokeLater()?
You could use some type of timer for this, possibly a ScheduledExecutorService which would be run in the background of Swing, perhaps with a SwingWorker. Then the process would be called background to the Swing thread, and you can update the GUI via publish/process.
Does the entire block of code go inside invokeLater or just the updating the GUI part. I feel like the entire code should go inside invokeLater but someone told me just to update the GUI such as (text.setText()) inside invokeLater().
As mentioned, your GUI needs to start up inside of a Runnable that is passed into a call to invokeLater(...). As for while your program is running, if the background code is run using a SwingWorker then usually there is no need a call to invokeLater(...). That is one of the reasons for using a SwingWorker rather than a plain vanilla Thread.
Edit 2
You state:
one last question I just came across while testing..inside an action performed I made the buttonclick change textfield to say hi, then I put in a try catch for Thread.sleep(1000) then change textfield to say ho. How come the result only outputs ho? it doesnt show hi, I tested with numbers and can see the program locking up. I know using a thread will fix this but just wondering why it wont display the output if I put a sleep.
When you call Thread.sleep(...) you put the calling thread, here the Swing Event Dispatch Thread or EDT, to sleep. Since it is responsible for all Swing painting and user interaction, the whole application goes to sleep, and the GUI is unable to perform any updates until the sleep has completed. This is precisely why you must use a background thread to perform this sort of thing.
I have a java app in which I use a thread. My thread runs every 20 seconds but, when it runs it kind of blocks the UI ... i. e. whenever the thread is running and the user clicks on button on anything on UI it doesnt respond sometimes.
Could anyone tell me a solution to this problem.
in java Swing, any change made to the state of the UI should be done in a single pre-existing thread called the EDT (event-dispatcher thread).
if that's not the case, you typically experience weird glitches / freezes. one of the most common symptom is that part of the UI becomes gray (except since java 1.6, where the ui is still painted like before, but unresponsive).
the good way to go is to use a dedicated method to queue your changes to the UI in the EDT :
SwingUtilities.invokeLater(Runnable toRunInEDT);
note that if you call invokeLater, the runnable is executed after all currently queued event have been dispatched. that means that the next line of code could be executed before the code in the runnable. there is a synchronous version as well (which should not be executed from the EDT):
SwingUtilities.invokeAndWait(Runnable toRunInEDT);
Some additional tips, on top of what edralzar said:
You can use the convenience method SwingUtilities.isEventDispatchThread() to check if code is in fact running on the event dispatch thread. And, like edralzar said, any code that creates GUI components, modifies the state of GUI components or reads the state of GUI components should run on the Event Dispatch Thread.
Another thing to consider, however, is that code running on the EDT should be able to execute rather quickly. So you cannot just solve things by running everything on the event dispatch thread. If you do the following, your GUI will be frozen for five seconds:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e){
//Ignored in this example
}
}
});
Why is it frozen? Because all GUI events and GUI updates are performed on the EDT, and if the EDT sleeps for 5000 miliseconds, no GUI updates can be performed during that time.
This article might be an interesting read.
Sounds to me like the thread you're referring to (that runs every 20 seconds) is also the thread that governs the UI.
The solution is to separate the two processes onto different threads.
My question is related to SwingUtilities.invokeLater. When should I use it? Do I have to use each time I need to update the GUI components? What does it exactly do? Is there an alternative to it since it doesn't sound intuitive and adds seemingly unnecessary code?
Do I have to use each time I need to update the GUI components?
No, not if you're already on the event dispatch thread (EDT) which is always the case when responding to user initiated events such as clicks and selections. (The actionPerformed methods etc, are always called by the EDT.)
If you're not on the EDT however and want to do GUI updates (if you want to update the GUI from some timer thread, or from some network thread etc), you'll have to schedule the update to be performed by the EDT. That's what this method is for.
Swing is basically thread unsafe. I.e., all interaction with that API needs to be performed on a single thread (the EDT). If you need to do GUI updates from another thread (timer thread, networking thread, ...) you need to use methods such as the one you mentioned (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).
Swing is single threaded and all changes to the GUI must be done on EDT
Basic usage for invokeLater()
Main methods should be always wrapped in invokeLater()
Delayed (but asynchronously) action/event to the end of EventQueue,
If EDT doesn't exists then you have to create a new EDT by using invokeLater(). You can test it with if (SwingUtilities.isEventDispatchThread()) {...
There exists invokeAndWait(), but till today I (just my view) can't find a reason for using invokeAndWait() instead of invokeLater(), except hard changes into GUI (JTree & JTable), but just with Substance L&F (excellent for testing consistency of events on the EDT)
Basic stuff: Concurrency in Swing
All output from background tasks must be wrapped in invokeLater()
Every Swing application has at least 2 threads:
The main thread that executes the application
The EDT (Event Dispatching Thread) is a thread that updates the UI (so the UI will not freeze).
If you want to update the UI you should execute code within the EDT.
Methods like SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait allow you to execute code by the EDT.
My question this time is related to SwingUtilities.invokeLater: When should I use it?
What is key to understand is that Java has a separate thread (EDT) handling Swing related events.
You should use invokeLater() to display the main JFrame of a desktop application (for example), instead of trying to do it in the current thread. It will also create the context for graceful closing of the application later.
That's about it for most applications.
Do I have to use each time I need to update the GUI components? What does it exactly do?
No. If you modify a GUI component, it will trigger an event which is registered for later dispatching by Swing. If there is a listener for this event, the EDT thread will call it somewhere down the road. You don't need to use invokeLater(), just set your listeners on components properly.
Keep in mind that this thread is the same thread drawing frames etc... on your screen. Hence, listeners should not perform complex/long/CPU intensive tasks, otherwise your screen will freeze.
Is there an alternative to it since it doesn't sound intuitive and adds seemingly unnecessary code?
You don't need to write more code than displaying your application with invokeLater() + listeners you are interested in on component. The rest is handled by Swing.
Most user-initiated events (clicks, keyboard) will already be on the EDT so you won't have to use SwingUtilities for that. That covers a lot of cases, except for your main() thread and worker threads that update the EDT.
Why is it necessary to put GUI update code in SwingUtilities.invokeLater()?
Why cant it be internally taken care of by Swing itself? Why does the caller have to care about how swing handles UI updates?
Swing objects are not thread safe. SwingUtilities.invokeLater() allows a task to be executed at some later point in time, as the name suggests; but more importantly, the task will be executed on the AWT event dispatch thread. When using invokeLater, the task is executed asynchronously; there's also invokeAndWait, which won't return until the task has finished executing.
Some information about the decision not to make Swing thread-safe can be found here: Multithreaded toolkits: A failed dream? [Archived]
Because GUI updates must be done in the event dispatch thread. If you're operating in a different thread, doing the update in invokeLater yanks it out of your thread and into the event thread.
More explanation here: http://www.oracle.com/technetwork/java/painting-140037.html
The smart thing to do with big updates (like repopulating a JTable from the database) on Swing is to get the underlying model, do the updates on the model in your thread, then fire off a notification using invokeLater. That keeps your gui responding to events and redrawing. If the update is going to be very extensive, you can even fire off these notifications with invokeLater at regular intervals while you're updating, like every second or two.
Swing is single-threaded. Every update to the UI must happen from the so-called EDT – the event-dispather thread which is the main GUI thread Swing (and I think AWT) uses. If you don't do this, then weird things can or will happen (though I like Windows Forms better here which just throws an exception if you do it wrong).
That being said, you don't need to wrap every single UI operation into SwingUtilities.invokeLater() – if the code you're writing is already executed by the EDT this isn't needed. So the ActionListener for a button click doesn't need this. But a listener on an external object, running in some other thread, that updates a JLabel somewhere – there you need it.
Swing was not written to be a thread safe GUI toolkit so all GUI updates should happen from a single thread to avoid any deadlocks. In Swing this is the Event Dispatcher Thread (EDT).
See Concurrent in Swing from the Java tutorial for more details. It also references this blog entry on why it is hard to write a multithreaded GUI toolkit.
All the painting of the components should be performed in a single thread, so, they are rendered properly. That way the component will know, what part has already been painted and which part hasn't.
If you invoke a "painting" related method ( paint, update, paintComponent, show, setVisible, pack etc. ) outside the EDT, you'll be trying to paint in two different threads, and that may bring problems.
When you need to use another thread to update the UI, you should invoke it with the invokeLater facility, which in turn will put it in the EDT for you, so you still paint in the same thread.
You don't need to use it, if you're coding in a method that runs in the EDT already ( for instance, actionPerformed or paint or one of those ) Or if you are executing code not UI related ( for instance, processing files in the background etc. )
To better understand all these concepts read:The single thread rule
SwingUtilities.invokeLater()
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI.
...
Repeating others: Swing is not thread safe so one thread must do all the updates to avoid concurrency problems. invokeLater is an utility method to execute something inside the event processing thread.
Why doesn't Swing does it internally: this is my impression... I think because it would be overkill -to check every place where an update is taking place. It would bloat the Swing code, dificult the review and maintainability of the code.
By the other hand it's not that dificult for an application to know if it's not executing inside the GUI thread and call invokeLater. It will be when the own application launched some thread before.