How to refresh ProgressMonitor in Swing? - java

ProgressMonitor is designed to handle long operations, but if used directly, then it does not refresh.

Thread worker = new Thread() {
#Override
public void run() {
//Code, that's freezing your gui
}};
worker.start();

Related

TimerTask can not update UI?

new Timer().schedule(new TimerTask() {
public void run() {
KeyBoardUtil.showKeyBoard(et_search);
}
}, 300);
I show the keyboard use TimerTask,and it runs fine.
how to explain it?
You can use runOnUiThread :
runOnUiThread(new Runnable(){
public void run() {
// Your code
}
});
Or
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
#Override
public void run() {
// Your code
}
};
mainHandler.post(myRunnable);
developer.android.com
In the previous lesson you learned how to start a task on a thread managed by ThreadPoolExecutor. This final lesson shows you how to send data from the task to objects running on the user interface (UI) thread. This feature allows your tasks to do background work and then move the results to UI elements such as bitmaps.
Every app has its own special thread that runs UI objects such as View objects; this thread is called the UI thread. Only objects running on the UI thread have access to other objects on that thread. Because tasks that you run on a thread from a thread pool aren't running on your UI thread, they don't have access to UI objects. To move data from a background thread to the UI thread, use a Handler that's running on the UI thread.

Java SWT UI Thread freeze even if run in new Thread

I have a problem with a long running task.
After my dialog is shown I want to scan a ftp directory. This task takes some time so I need to run this task no in the UI thread.
My idea was
#Override
protected void postDialogOpen() {
// if invoked via menu button
if (!scanFtp) {
final Display display = Display.getDefault();
new Thread(new Runnable() {
#Override
public void run() {
//initProgressWaitViewer();
scanFtpServer();
//closeProgressWaitViewer();
display.syncExec(new Runnable() {
#Override
public void run() {
updateTree();
}
});
}
}).run();
}
}
But during the execution of scanFtpServer() my dialog is not movable and if I click on it it becomes "unresponsible".
Is there something I am doing wrong?
When calling method run() in class Thread, you are executing the method on the caller thread, just like calling any other method. If you want to spawn a new thread and execute method run() in that thread, you need to call method start() instead, that will do all the work of setting up the thread and running it.
So replace
}).run();
with
}).start();
Try to do .start() instead of .run() .

Updating buttons inside or outside of SwingWorker?

I want to disable a number of buttons/menu items of my GUI while a SwingWorker thread is running. The thread is started when a button is clicked.
It looks like the while loop in my code causes the CPU load to go up significantly. Did I get something wrong about how to determine if a SwingWorker thread is still running?
The CPU load's definitely lower when I update the buttons/menu items inside the SwingWorker thread. However, I felt like that shouldn't be the SwingWorker thread's job. Should it?
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
menu.setEnabled(false);
MySwingWorker worker = new MySwingWorker();
worker.execute();
while (true) {
if (worker.isCancelled() || worker.isDone()) {
menu.setEnabled(true);
break;
}
}
}
});
t.start();
}
});
Swing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT). Doing so from t is incorrect. As suggested in examples cited here, condition your GIU elements on the EDT before starting the worker, and update the GUI in process() or done().

Trouble with SwingUtilities.invokeLater() updating GUI

I have been trying this all day in different variations with little success. Could someone please help explain what I am doing wrong? I am just a beginner with regards to threads.
private JTextArea text = new JTextArea();
private JButton button = new JButton("Cancel");
public StatusFrame() {
text.setEditable(false);
this.add(text);
this.add(button, BorderLayout.EAST);
this.setSize(new Dimension(150, 100));
this.setVisible(true);
}
public void updateStatus(String textIn) {
text.setText(textIn);
}
public JButton getButton() {
return button;
}
In another class, I am calling methods which may take a while to complete. I want to be able to call the StatusFrame.updateStatus() method to keep the user informed on the progress.
This is what I have:
someMethod() {
// prevent GUI from freezing using threads
final Runnable r = new Runnable() {
public void run() {
status = new StatusFrame();
}
};
SwingUtilities.invokeLater(r);
//do something
status.update("process 1 completed");
//do something else
status.updateStatus("Process 2 completed");
}
The frame appears but none of the code after the runnable appears to be run/processed. It just stops/blocks/something. But the GUI remains active
Thanks for any advice.
P.S.: I have tried using invokeAndWait() method but again not sure if I am doing it the right way. For now a quick fix would be preferred as I have not learned much about threads yet. Any instructions are welcome.
You have the concepts backwards.
Here's your code
someMethod() {
// prevent GUI from freezing using threads
final Runnable r = new Runnable() {
public void run() {
status = new StatusFrame();
}
};
SwingUtilities.invokeLater(r);
//do something
status.update("process 1 completed");
//do something else
status.updateStatus("Process 2 completed");
You should execute the long running code in a thread, and use the SwingUtilities invokeLater method to update the GUI.
someMethod() {
// prevent GUI from freezing using threads
final Runnable r = new Runnable() {
public void run() {
status = new StatusFrame();
}
};
new Thread(r).start();
// inside the StatusFrame
//do something
SwingUtilities.invokeLater(new Runnable() {
public void run() {
update("process 1 completed");
}
);
//do something else sometime later
SwingUtilities.invokeLater(new Runnable() {
public void run() {
update("Process 2 completed");
}
);
I don't know if I was clear in my answer.
Execute SwingUtilities.invokeLater when you start your Java application to make sure Swing components are on the Event Dispatch thread (EDT).
From the EDT, invoke long running processes as a runnable thread.
In the runnable thread, since you're not on the EDT, execute SwingUtilities.invokeLater whenever you're updating Swing components. This ensures that Swing components are updated on the EDT.
Every Swing application should start with a class like this:
import javax.swing.SwingUtilities;
import com.ggl.text.entry.model.TextEntryModel;
import com.ggl.text.entry.view.TextEntryFrame;
public class TextEntry implements Runnable {
#Override
public void run() {
new TextEntryFrame(new TextEntryModel());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TextEntry());
}
}
This class does 3 things.
Constructs the GUI data model.
Constructs the GUI JFrame.
Ensures that the Swing components are on the EDT.
You'll need to call the updates on EDT too. I would suggest to sleep on the main thread, to give GUI a chance to show up before any other work:
someMethod() {
// prevent GUI from freezing using threads
Runnable r = new Runnable() {
public void run() {
status = new StatusFrame();
}
};
SwingUtilities.invokeLater(r);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
//do something
r = new Runnable() {
public void run() {
status.update("process 1 completed");
}
};
SwingUtilities.invokeLater(r);
//do something else
r = new Runnable() {
public void run() {
status.update("Process 2 completed");
}
};
SwingUtilities.invokeLater(r);
}
See Concurrency in Swing.
You may find using a Swing Worker easier to work with since it uses a Thread and has methods that will allow you to update the GUI properly.

Java SwingWorker locks up GUI

I have the following code...
runNow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
final Search s = (Search) node.getUserObject();
// Swing worker
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
s.run();
return null;
}
#Override
public void done() {
window.updateResultsPanel(s.getResults(), s.getName());
}
};
worker.run();
}
});
This is a popup menu action which should create a new SwingWorker, free up the GUI, do some work, then update the results of the window. However, right now when I click the menu item the GUI becomes locked up until the work completes which is baffling, the whole point of using a SwingWorker is so that won't happen.
Any ideas as to what I'm doing wrong would be greatly appreciated.
-Cody
You should be calling SwingWorker#execute to start the worker, not run
Run is exposed by the Runnable interface, but execute actually schedules the worker to run at some time in the future.
Have to change method SwingWorker.run() to SwingWorker.execute() and it worked like a charm.

Categories