Swing invokelater freeze - java

im calling invokeLater direcly from button on actionPerformed with this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int temp = (jComboBox1.getSelectedIndex() + 1);
heavyProccesingFunction();
}
});
}
and that still freezes the GUI. Why? I get the same result without using the invokelater function.
should I Use
Thread queryThread = new Thread() {
public void run() {
instead?
Edit:
Thanks, new thread should be used.

invokeLater still ends up running the code on the dispatcher thread - just later. The aim of invokeLater is to allow background threads to post work on the event dispatcher thread.
It sounds like you should indeed create another thread - or use a thread pool for the same sort of effect, or SwingWorker for example. Whatever you do, you need to avoid running your slow method on the event dispatcher thread.

Related

Should i call InvokeLater inside a thread created in the EDT?

what happens if i modify my gui inside a thread created in the edt?
When i say "created in the edt" i actually say that the thread declaration and its starts are in a block of code surrounded by:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
Thread t= new Thread(new Runnable(){
public void run(){
txtField.setText("setting...");
}
});
t.start();
}
}
will this modify my gui without side effects? or should i call again invokeLater inside Thread "T"?
It doesn't matter whether you instantiate and run the thread in EDT. It will be a new thread, running independently from EDT, and therefore it will not be safe to modify the GUI from it. All Swing modifications must be done using invokeLater().

Waiting for frame creation

i have problem in java and I do not know him and I resolved.
I created a simple program that inserts into the text JPanel using for and sleep function.
Like this(This is an example):
public class example{
JFrame frame....
..
..
public example(){
//ini frame and label.. then..
String s = "abcqweewqewqewqewqweqwqeweqweqwq";
//DO ANIMATION
try
{
for(int i = 0;i<s.length();i++)
{
JLABEL.append(String.valueOf(s.charAt(i)));
Thread.sleep(10);
}
}catch(Exception ex){}
}
public static void main.......{
new example();
}
}
It works perfectly (writes characters after a certain time interval)
But, if i call this main using other class-So waiting until everything renders and then the window appears (so does not animation).
Where is a problem? I hope, you understand me.
Swing is single threaded, and properly written swing code runs in the event dispatch thread. Your sample breaks the threading rule by creating the GUI outside the EDT, and also runs the loop in the main thread. Normally, when created correctly in the EDT, or as a response to an event from a button click or similar, the loop blocks the event dispatch thread so that no drawing can happen until the loop has completed.
You get that behaviour if you initialize the GUI in the event dispatch thread:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new example()
}
});
}
The proper way, instead of sleeping in the EDT, is using a Swing Timer.
To sum the above: your code appears to work only because it has the bug that it runs some of the UI code outside the event dispatch thread.

Thread inside invokeLater in Blackberry

I have a thread inside an invokeLater method in Blackberry like:
startButton.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field arg0, int arg1) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Thread thread = new Thread(){
public void run() {
uploadFile();
}
};
thread.start();
}
});
}
I have a thread because I want to run that function in the background and want to be able to do other stuff while its doing its job. What I am wondering is if this is a good approach. Do I really need the invokeLater in this case ?
Short answer: no.
Long answer:
InvokeLater puts the Runnable on the event queue so that, in time, when the event loop sees the Runnable it will execute it on the event thread. Since you are calling invokeLater in the fieldChanged method of a FieldChangeListener, you are calling it from the event thread. Unless what you want to do is delay the start of your thread to some unknown later time then no you don't need to use invokeLater.

What is the ways updating jProgressBar?

I need to update jProgressBar in method which read from file and do some operations.
I tried to update progress bar by this method:
public void progressUpdate(int percent) {
System.out.println("Update = "+percent);
synchronized (jMainProgressBar) {
jMainProgressBar.setValue(percent);
}
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jMainProgressBar.updateUI();
jMainProgressBar.repaint();
}
});
}
how ever this works only then when method is done. But if i continuously updating by this method then nothing happens.
Maybe some know how to improve this method?
It also would be nice for more suggestion Worker thread and else.
You probably want to do
public void progressUpdate(final int percent) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jMainProgressBar.setValue(percent);
}
});
}
Don't use Thread. Use Timer. Refer the following:
JProgressBar in Napkin look and feel is not working
How to Use Progress Bars
http://www.roseindia.net/java/example/java/swing/SwingProgressBar.shtml
Read Concurrency in Swing for more information
Based on the comments you provided (but not from the question!) you are performing heavy work on the Event Dispatch Thread (EDT). This blocks that thread and avoids any scheduled repaints to be performed. That is why you only see the update of your JProgressBar after the work is finished, as that is the moment the EDT becomes available to perform the repaint.
The solution is already provided in the links posted by others but it basically comes down to:
perform the work on a worker thread
update the progress on the JProgressBar on the EDT
The two most common ways to achieve this are using a SwingWorker or using SwingUtilities.invokeLater from the worker thread.
All relevant links can be found in the answer of Yohan Weerasinghe
Check this out
Timer barTimer;
barTimer=new Timer(100,new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
barvalue++;
if(barvalue>jProgressBar1.getMaximum())
{
/*
* To stop progress bar when it reaches 100 just write barTime.stop()
*/
barTimer.stop();
barvalue=0;
}
else
{
int a=(int)jProgressBar1.getPercentComplete();
jProgressBar1.setStringPainted(true);
jProgressBar1.setValue(barvalue);
}
}
});
barTimer.start();
Check the code at this link
http://java23s.blogspot.in/2015/10/how-to-implement-progress-bar-in-java.html

Java Altering a GUI from a different class

So my program has multiple classes and after one of them has run, it'd like it so it appends the text area in the main class GUI with a 'finished' message
ta.append("Search Complete\n");
and this is the code that needs to complete
statCl.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent e) {
try {
ta.append("Searching...\n");
task.execute();
} catch (Exception IOE) {}
}
});
So it is in the class where task where actual code runs.
Any advice or help would be amazing, thanks.
If the task.execute() method doesn't start launch an operation in another thread, then the GUI will be freezed, and nothing will apear in the text area until the operation is finished. So you might just have
ta.append("Searching...\n");
task.execute();
ta.append("Finished");
If the operation is launched in a new thread, then this thread should append in the text area, but it should make sure this append is done in the event dispatch thread (EDT). Your code could thus look like this :
public class Task {
private JTextArea ta;
public Task(JTextArea ta) {
this.ta = ta;
}
public void execute() {
Thread t = new Thread(new Runnable() {
// perform the long operation
// at the end, update the text area, in the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ta.append("finished");
}
});
}
t.start();
}
}
You might also look at SwingWorker, which is designed just for that (and other things like progress update). There is a code example in its class javadoc which does just what you're trying to do.
You should not be performing long-running task on EDT (event dispatching thread):
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
Swing does all it's work on EDT, so you should not block EDT, e.g. run intensive tasks on it. Note: all event handlers are executed on EDT.
So there are two challenges:
Run intensive tasks in a background thread.
Update GUI, which must be done on EDT.
Use SwingWorker to solve this two issues.

Categories