SwingUtilities.invokeLater ... is there an invokeNow? - java

I had a problem earlier where I was trying to add objects to my canvas but the SwingUtilities.invokeLater hadn't really done its job yet. I really need to be able to add things reliably to this JPanel but I keep running into this same error. Is there a better alternative to the below code?
private void startNewGame() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameFrame = new InvadersGameFrame();
}
});
}

See SwingUtilities.invokeAndWait(Runnable) which:
Causes doRun.run() to be executed synchronously on the AWT event dispatching thread. This call blocks until all pending AWT events have been processed and (then) doRun.run() returns. This method should be used when an application thread needs to update the GUI.

Related

SwingUtilities.InvokeLater and ButtonListeners

just a question about SwingUtilities.InvokeLater().
To my understanding, any time I update my Swing interface I need to call SwingUtilities.InvokeLater to get onto the EDT. Does this need to be done if I am attempting to update my GUI from a button listener, as they button events are already on the EDT?
i.e, would i have to..
public void mouseClicked(MouseEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//GUI updates
}
});
}
or would I simply be able to...
public void mouseClicked(MouseEvent e) {
//GUI updates
}
Furthermore, Does the same logic apply if I am calling a method on an object that will update the GUI?
any time I update my Swing interface I need to call SwingUtilities.InvokeLater to get onto the EDT
Correct. This includes any time you update the model of the component, since this will also result in the repainting of the component.
Does this need to be done if I am attempting to update my GUI from a button listener, as they button events are already on the EDT?
Again correct. Since the code is automatically invoked on the EDT you do not need to manually add it to the EDT using the invokeLater().
You typically use the SwingUtilities.invokeLater() if your code is executing on a separate Thread and part of that logic needs to update a GUI component.
Updating this message :
Swing event handling code runs on a special thread known as the event dispatch thread. So all of the component(button, checkbox, radio button etc.,) actions are handled on EDT. So no need to have SwingUtilities.invokeLater() inside your button action as it always runs on EDT.
Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.
So if you are planning to perform a long running task that could affect a GUI inside an action then better go for Worker Threads or Background Threads.
SwingWorker has doInBackground(), done() and process() methods to handle the long running tasks well without impacting the GUI.
Go through below links to get more info
Why does SwingUtilities.invokeLater() cause JButton to freeze?
What does SwingUtilities.invokeLater do?
https://www.javacodegeeks.com/2012/12/multi-threading-in-java-swing-with-swingworker.html

How to set anchor pane visible just before subprogram call in javafx?

The purpose of the following code is to handle menu option choice. Because processing in method update() takes quite a bit time, I want to display info before this takes place.
My info is simply an anchor pane with label in it, which normally is set to be not visible. Unfortunately, the code below sets anchor pane visible only for a very short time after update() terminates. How can I do it properly?
public void updateRates(ActionEvent event)
{
updateInfo.setVisible(true);
update();
updateInfo.setVisible(false);
}
Most user interface libraries are single threaded. That thread is created by and controlled by the UI system. All listeners are called on that thread. When the UI thread is held up, such as when your update() call is running, the UI does not redraw at all, and keyboard events and mouse events will “pile up” in the event queue, appearing to be ignored, until the thread is allowed to continue running (at which point all of them will be processed immediately, in order).
For this reason, lengthy operations must never execute on the UI thread. One option is to run a Task in a different thread:
Task<Boolean> updater = new Task<Boolean>() {
#Override
public Boolean call() {
updateValue(true);
update();
return false;
}
};
updateInfo.visibleProperty().bind(updater.valueProperty());
new Thread(updater).start();
You could also create a Thread from a plain Runnable:
updateInfo.setVisible(true);
Runnable updater = new Runnable() {
#Override
public void run() {
update();
Platform.runLater(() -> updateInfo.setVisible(false));
}
};
new Thread(updater).start();
Platform.runLater is required in this case, because user interface objects, including all JavaFX Nodes, may only be accessed and modified in the UI thread. If your update() method is manipulating any Nodes, it will need to use Platform.runLater to do so.
The Task class has built-in support for showing work progress in the UI, but since you haven’t included the code for your update() method, I can’t tell you whether that support would be useful in your situation.

Why does running a thread loop within an AWT component prevent the WindowHandler from executing?

I modified the sample code for Activator posted on the Oracle/Sun AWT tutorial page here
The modification is as follows
f.add(new MyCanvas(f.getGraphicsConfiguration()),
BorderLayout.CENTER);
The paint method in MyCanvas is overridden as follows
MyCustomRunnable mcr = new MyCustomRunnable();
Thread th = new Thread(mcr);
th.start();
while(Thread.currentThread().isAlive()){
mcr.getData();
//do UI stuff
Thread.yield();
}
Similarly MyCustomRunnable has a corresponding loop in run()
public void run(){
while(Thread.currentThread().isAlive){
//do Stuff
Thread.yield();
}
}
The Runnable, and Canvas paint (both) run a loop. With this bit of code running, System Menu close on the UI window are not invoked. Why?
The short answer is that paint() is called on the event thread, which is also the thread that handles all UI events, and you are taking over that thread and putting it into an infinite loop.
When you are doing this in the paint method...
while(Thread.currentThread().isAlive()){
...
}
... the "current thread" you are working on is the same thread you entered that method on, which is the "event dispatch thread". I would guess that what you really wanted was to run a background thread that periodically repaints the view. You could do this in the constructor of your AWT component:
new Thread() {
public void run() {
while(runBackgroundThread) {
mcr.getData();
repaint();
}
}
}.start();
Note that I also created a boolean variable runBackgroundThread which would be a volatile field in the component class. Setting it false would stop the loading thread. In contrast, Thread.currentThread().isAlive() will always be true - the currently running thread must by definition be alive.
0Almost certainly because your thread is keeping control and not letting the window events thread to run.
There is no point starting a background thread if all you are going to do is to wait for it to finish. Instead you can make the background thread do what you want to happen when it finishes.

How to update JFrame Label within a Thread? - Java

I have tried a lot, but can't seem to get it to work.
I was told to use EDT with the following example.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Modify the GUI here
}
});
I have read on this topic a lot and still don't understand. I get what a thread is, but the .invokeLater still makes no sense to me. Honestly if you can explain in detail this it would be a big help!
Goal of Program: To get the randomly generated key that is constantly created every second to update itself afterward in the GUI.
So there is an EDT (Event Dispatch Thread). All actions that appear on your screen are executed by the EDT. There is only one EDT per Swing application.
You are in some arbitrary thread and you want to update the GUI through that thread? Well like I said there is only one EDT for each swing application, so you have to tell that EDT to display the label (or whatever context you want).
The idea here, is you push this Runnable onto a queue that the EDT pulls from. Eventually, your runnable will be processed by the EDT when all other actions before it are completed.
I recommend you get the book Filthy Rich Clients. There's a chapter where they explain Swing's threading model to great detail.
Basically in Swing, any code that modifies the GUI should be executed in the Event Dispatcher Thread. The SwingUtilities class that you are using there provides you with an easy way to post events to the event queue that is then dispatched by the EDT. That's what the invokeLater method does, it takes a new Runnable() as argument which is ultimately executed on the EDT.
From the book:
The invokeLater() implementation takes
care of creating and queuing a special
event that contains the Runnable. This
event is processed on the EDT in the
order it was received, just like any
other event. When its time comes, it
is dispatched by running the
Runnable’s run() method.
This is a pretty common element of all GUI programming. You have one thread that handles drawing the GUI, getting input, and running callbacks. If another thread tries to change the GUI related objects, it will conflict with the GUI thread. Say, for example, it was half way through drawing something and you change the color from a different thread.
All invokeLater does is queue up something for the GUI thread to run. By "later" it's really runs almost instantly but the current thread doesn't have to wait for it. The GUI thread may be doing a draw or waiting for a callback to return which would delay executing the code you gave it.
Needs to be a member so we can change it and still use it from an inner class
protected long secret=0;
... this needs to be in your code somewhere it'll get run...
JFrame f = new JFrame("foo");
new Thread(){
public void run() {
for(;;){
try {
sleep(1000);
} catch Interrupted (Exception ix){
return;
}
// TODO update your secret key here
// please don't use random()
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle("secret "+x);
}
});
}
}
}).start();
....
Only ever update Swing from the EDT so that it paints properly.
When you are in the EDT ( running code in an event handler) you can call paintImmediately() if you really must.
If you're all looking to do is update the UI on a known schedule, try something like the following. This assumes that a JFrame is the component you wish to update every 1 second.
private static final int WAIT_LENGTH = 1000; // 1 second
private JFrame frame = new JFrame();
// Thread will update the UI (via updateUI() call) about every 1 second
class UIUpdater extends Thread {
#Override
void run() {
while (true) {
try {
// Update variables here
}
catch (Exception e) {
System.out.println("Error: " + e);
}
finally {
frame.repaint();
Thread.sleep(WAIT_LENGTH);
}
}
}
}
To start this thread:
UIUpdater t = new UIUpdater();
t.start();

How to update SWT GUI from another thread in Java

I am writing a desktop application using SWT. What is the simplest way to update GUI controls from another thread?
Use Display.asyncExec or Display.syncExec, depending on your needs.
For example, another thread might call this method to safely update a label:
private static void doUpdate(final Display display, final Label target,
final String value) {
display.asyncExec(new Runnable() {
#Override
public void run() {
if (!target.isDisposed()) {
target.setText(value);
target.getParent().layout();
}
}
});
}
More here
There's a tutorial here.
"SWT does make a point to fail-fast when it comes to threading problems; so at least the typical problems don't go unnoticed until production. The question is, however, what do you do if you need to update a label/button/super-duper-control in SWT from a background thread? Well, it's surprisingly similar to Swing:"
// Code in background thread.
doSomeExpensiveProcessing();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
someSwtLabel.setText("Complete!");
}
});
You can actually just sent a message to the GUI thread that some modification has been changed. This is cleaner if you see it from MVC perspective.
When creating the separate thread from the main thread pass the Gui object to the new thread and u can access all the properties of that GUI object.

Categories