I know that using threads is more efficient than using c# DoEvents(), but I was still wondering whether there is an equivalent function in java. I googled for it, but I couldn't find anything.
You can use Thread.yield(), which is the java counterpart to relinquish the control of the processors voluntarily.
You can use EventQueue.invokeLater() to append a Runnable after all pending events. This have a result similar to C#'s DoEvents() that comes before the code you put inside the Runnable.run() method.
See Java documentation for EventQueue.
For example, if you want to let all GUI controls to lose the focus and their lost focus events to be execute, you can use the following code:
#Override
public void windowClosing(WindowEvent e){
// Clear the focus to allow last changes to be noted.
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
// We want to let other events (e.g. lost focus) run before we start closing.
EventQueue.invokeLater( new Runnable() {
#Override public void run() {
// Do actual closing...
}
});
}
Related
I'm building a user-interface with Java's swing library, and I've run into a problem.
When updating a text-area in a long method, there is a pause while the method runs, and then the text area is updated all at once, instead of a little bit at a time.
I managed to fix the problem using a new thread in the following manner:
private void jButtonActionPerformed(java.awt.event.ActionEvent evt) {
Thread x = new Thread() {public void run() {
// do things that update a text area
}}; x.start();
}
This works perfectly for having the text area update in small pieces, as opposed to all at once.
However, the only problem is that this method can only be called once or Java crashes. I read that this has to do with only being able to create the thread one time. How can I modify the code to keep the desired functionality?
Any help would be greatly appreciated.
Well, I doubt you codes crashing because of the Thread creation, because each time the method is called, you're creating a new Thread (you can't restart an existing instance of a Thread that has already been started (even if it's completed or not)), the likely cause is you're getting a concurrent modification exception because Swing is not Thread safe...
Probably the easiest solution would be to use a SwingWorker which will allow you to execute your long running task in the background, but provide easy to use functionality to update the UI safely, through the publish, process and done methods.
Do prevent possible issues, you might also consider disabling the button until the load action is completed, which will prevent people from mashing the button spawning multiple background processes...
Well you can make new object of the Thread and override all the method means runnable.
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Executed..*****");
}
}).start();
try this.
Just for comparison's sake, here is an example using SwingUtilities.invokeLater. I echo MadProgrammer's advice though, learning about SwingWorker is much more beneficial in the long term and gives better variable handling.
newGame.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent arg0) {
panelList.get("newGame").setEnabled(false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// this is where the heavy processing occurs
newGameButton();
// re-enables the button afterwards
panelList.get("newGame").setEnabled(true);
}
});
}
});
Also, once your code is working better, you can probably look into ways to optimise the speed of the update (even when dealing with Swing objects). The above call used to hang for a second or so, but I've got the delay to about 50 - 100ms or so with further work on the model :)
I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.
I've been told that I need to create a SwingWorker for a long-running directory tree walker whose "guts" are shown in pieces below. (To keep it short, I've removed lots of closing } and ) and other superfluous (to my question) stuff such as ignored catch clauses.)
When matching a given filename pattern, a filename (and other stuff) is written, by report(), to a text area:
public class TASK extends SimpleFileVisitor<Path> implements Runnable{
public static FileVisitResult disposition = FileVisitResult.CONTINUE;
private static void report(String s){
try{
Output.jTextArea1.append(s + "\n");
catch (Exception e){ aborted = true ; disposition = FileVisitResult.TERMINATE;}
public void run() {
disposition = FileVisitResult.CONTINUE;
Files.walkFileTree(p , this); // walkTreeFile calls visitFile() for each file.
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
report(f1.getFileName().toString());
return disposition;
main() just creates threads for GUI and Output:
public static void main(String args[]) { // main
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
gui = new GUI();
gui.setVisible(true);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
info = new Output();
When the "Search" button is clicked jbSearch...() makes the output window visible and instantiates TASK and the tree walk begins:
private void jbSearchActionPerformed(ActionEvent evt) { // this is in GUI
try {
TASK v = new TASK();
Thread t = new Thread(v);
t.start();
It all works fine BUT the output window flickers and looks hacked, so I need SwingWorker. But I can't say the following because TASK (or something) has to extend SimpleFileVisitor:
class TASK extends SwingWorker<List<String>, String>
So I'm looking for something to implement. My notes tell me "Because SwingWorker implements Runnable, a SwingWorker can be submitted to an Executor for execution" so I think I'm heading there next unless somebody stops me! (I've never used executors before.)
After I figure out how in involve SwingWorker, I assume I should do the following, probably in jbSearch...() in place of the 3 lines shown (just above):
TASK.execute();
I guess I have to make doInBackground() call visitFile(), which is what is applied to all the files in the walk. Is it MY responsibility to fill the array that doInBackground() returns? The Java tutorial for SwingWorker suddenly returns numbers which isn't defined anywhere to be an array or anythin else.
So I guess I have to make process() call (my) report(), which appends new info to the output window (text area). I assume that once doInBackground() fills the array of chunks, it will be easy to process them.
But where do I put get()? The Java tutorial for SwingWorker sort of suggests that get() isn't necessary, since the example writes to a text area and get() is merely used with System.out to display the same info on the console.
(EDIT) Oh yeah... What do I publish()? I guess I publish inside report().
But I'm posting anyway since I THINK the question and/or answer COULD be a valuable find for someone asking the next question about SwingWorker.
(EDIT) A big problem I think I face is that walkFileTree more or less "is" a loop, repeatedly calling visitFile() behind the scenes, ending when the tree ends or when the return value in visitFile() is set to TERMINATE. So do I just stick visitFile() in doInBackground() since it's more or less already in a loop? And then put publish() right after it?
But then how do I return an array?
Ug.
So I'm looking for something to implement. My notes tell me "Because
SwingWorker implements Runnable, a SwingWorker can be submitted to an
Executor for execution" so I think I'm heading there next unless
somebody stops me! (I've never used executors before.)
After I figure out how in involve SwingWorker, I assume I should do
the following, probably in jbSearch...() in place of the 3 lines shown
(just above):
TASK.execute();
Yes, SwingWorker#execute is the typical way to start a SwingWorker
I guess I have to make doInBackground() call visitFile(), which is
what is applied to all the files in the walk. Is it MY responsibility
to fill the array that doInBackground() returns? The Java tutorial for
SwingWorker suddenly returns numbers which isn't defined anywhere to
be an array or anythin else.
Anything you want done in the background should be called from this method.
Yes, you need to generate the result yourself. The actual value can be defined anywhere, but I personally define a local variable within the context of the doInBackground method
So I guess I have to make process() call (my) report(), which appends
new info to the output window (text area). I assume that once
doInBackground() fills the array of chunks, it will be easy to process
them.
In order for values to be processed, you need to first publish them. When these values are passed to process will depend on how intensive your background process is.
Overriding done and calling get will also allow you to access what was returned from doInBackground within the context of the EDT
But where do I put get()? The Java tutorial for SwingWorker sort of
suggests that get() isn't necessary, since the example writes to a
text area and get() is merely used with System.out to display the same
info on the console. If I don't need to call get(), maybe I'm closer
to a solution that I thought when I started this.
This will depend. Do you care about the result? If you do, I tend to call it within the done method, because, generally, I want to use the values within the EDT.
The important thing to know about get is that it is blocking, that is, it will wait until doInBackground returns
For example
I'm refactoring some code that runs a multi-stage process. Each step is inside a nested java.awt.EventQueue.invokeLAter.... call. It looks a little like this:
import java.awt.EventQueue;
public class NestedInvokeLater {
/**
* #param args
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
changeTabPanel();
copySomeFiles();
enableNextButton1();
upDateProgressBar(10);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
readInFiles();
doSomethingToFiles();
upDateProgressBar(15);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
doSomethingElse();
upDateProgressBar(100);
}
});
}
});
}
});
};
}
I am new enough at Java that I don't get the point of nesting these calls to add 'jobs' to the EDT, and I'm not 100% confident with fiddling with these calls either. I think I understand what the invokeLater call does, and what each step does. Please correct me if this understanding is wrong:
invokeLater is used to add some invocation to the list of jobs to be done in the Event Dispatch thread. Java then deals with when/how each invocation is done, ensuring that the EDT and in turn the GUI doesn't lock as it performs jobs 'in the background'.
Nesting these calls says to me that we should queue a set of jobs, one of which is to queue something, which will queue some jobs....one of which is to queue something. But the first inner invocation is only ever queued once the previous job is done. Everything occurs sequentially (this is in line of my understanding of the whole process), but I don't see why you would use nested requests to queue jobs to do so. I would have, if I was writing this from scratch, have simply created functions for each invocation and called them in turn.
I recognise, being only a novice at Java I am probably missing something huge that makes this nesting important. But there is no documentation of this, and no commenting in the code about the nesting.
What am I missing? What, if anything is the point in this code?
There is no point in doing so many nested invocations. It is based on a good intention, but it's badly implemented.
If you want to do this properly, use a SwingWorker.
The documentation of SwingWorker has a neat example of how you should implement performing several tasks in the background of the application (the PrimeNumbersTask class showed there).
Edit: Here's an example of what you should do with SwingWorker in your case.
class SequentialInvoker extends SwingWorker<Void, Integer> {
#Override
public void doInBackground() {
changeTabPanel();
copySomeFiles();
enableNextButton1();
setProgress(10);
readInFiles();
doSomethingToFiles();
setProgress(15);
doSomethingElse();
setProgress(100);
}
}
To actually show the progress on a progress bar, take a look at the following code, copied from the SwingWorker documentation:
JTextArea textArea = new JTextArea();
JProgressBar progressBar = new JProgressBar(0, 100);
SequentialInvoker task = new SequentialInvoker();
task.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});
With this code, your progress bar will show the progress as the SwingWorker works.
One advantage of doing it this way is that other queued up things get to run in between. So, in between the section that does changeTabPanel() and the part that does readInFiles(), the GUI will get to respond to the user clicking on a button etc...
The actual implementation is a bit of a confusing mess and illustrates (IMHO) why anonymous functions were not such a good idea. Your inclination to make the three parts "real" functions and call them sequentially is a good one. But, to maintain the same logic, what you really need to do is make them three runnables and have each invokeLater the subsequent one.
And #Cyrille is correct that doing these major tasks on the EDT is poor practice.
There are three jobs that are used in invokeLater here. Each one does a costly thing, call updateProgressBar and then adds the next job to the EDT.
The thing is, if the code just continued to the next costly thing instead of calling invokeLater to do it, the EDT would not have the chance to repaint the progress bar to show the new value of it. This is probably why the work is broken in three invokelater calls.
Now, this is not what I would call a good code. This is pretty bad practice: one should not do a long process in the EDT because it blocks everything and makes the GUI unresponsive. This should be changed so that the process is done in a separate thread, and then only call invokeLater to update the progress bar.
Edit: To answer more generally the question in the title: there is almost never a sensible reason to nest calls to invokeLater. When you are doing this, you say "queue this job so that it is done in the same thread but later when you feel it would be good". So it gives a chance to the rest of the GUI to repaint itself, like here. But it only makes sense if you have a long running process in the EDT, which you should always avoid.
The code you posted makes absolutely no sense to me - you can just write everything sequentially because you have no parallel threads running which might post events on the EDT. You need the first invokeLater() though, as you use Swing components.
But as your code suggests you are doing some relatively lengthy operations: reading files, do something with them, ... You should run these methods in a new worker thread, NOT the EDT. And, in the run() method of these worker threads, you'll need a call to EventQueue.invokeLater() to have your GUI updated.
What is the right way to update the UI after doing some operations on Swing?
For example, after clicking a button, a method is called that may be almost instant or take some seconds. In fact, all the applicaton logic is done remotely through a web service, so it's normal to wait a little bit for the application to respond.
My eventhandler for a button may look like these:
myButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
//callWebService();
//do stuff
//updateUI(); // <----- repaint? revalidate? what?
}
});
My current implementation calls the updateUI method which internally call validate() and repaint() to the parent component that holds the UI. This works, but sometimes I can see the screen flickering. Am I doing it wrong? Is there a better way to do it?
The right way would be to use SwingWorker, but if you want to do it manually you'll have to implement the following pattern:
#Override public void actionPerformed(java.awt.event.ActionEvent evt) {
new Thread() {
#Override public void run () {
//callWebService();
//do stuff
SwingUtilities.invokeLater(new Runnable(){
#Override public void run() {
//updateUI(); // <----- repaint? revalidate? what?
}
});
}
}.start();
}
For the repaint/revalidate question, normally call revalidate() then repaint(). this is, of course, only valid for component that you manually draw. For components that you reuse, just call their value change methods.
I'd personally use SwingWorker for this, despite some of the other comments / answers:
Despite the fact keeping the UI responsive isn't part of the original question, it's good practice to do this anyway (I can't think of a single good reason to lock up the EDT with lengthy processing.)
It provides a done() method that can be implemented which will be executed on the EDT by default when the task is complete, saving the need for manually wrapping up things in invokeLater()
It's more extensible, providing the framework to allow information like progress to be added easily later if it's so desired.
I've seen a lot of SwingWorker hate in general recently, and I don't understand why. It's a nicely designed, extensible class specifically for purposes such as this that works well. Yes, you could wrap things up in threads and launch them and have them wrap other methods up in invokeLater(), but why reinvent the wheel when there's a better one available for free?
Take the long running task to a different thread. Send events back to the AWT Event Dispatch Thread (EDT) to update the GUI with java.awt.EventQueue.invokeLater.
You shouldn't normally have to do anything : if you use the swing components methods, or the methods of their model, the necessary events are fired and the GUI should update itself automatically.
This won't be the case if you define your own models (and forget to fire the necessary events, but then it's a bug in your models, and it should be fixed there.