• Post Reply Bookmark Topic Watch Topic
  • New Topic

Updating Swing control in loop  RSS feed

 
Mike London
Ranch Hand
Posts: 1476
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is a follow up to my message on this form with a bit more detail.
I'm using the ideas from the threading chapter in Core Java II, Advanced features, but am having basic problems.
I'm posting my code below for anyone's comments or help.
------------------
I created a special class called "LabelUpdater", which uses the EventQueue.InvokeLater method. Then, from my main class, I create the start method on this thread class.
The goal of using this InvokeLater in the code below is that it's "supposed" to allow you to update a SWING control while your program is running (for example, to update a JTextField as I'm trying to do with progress on what's happening in the loop).
However, the GUI paining is not improved. I don't see anything on the JTextField until the last loop iteration (which is what happens when I just try to update the JTextField directly in the loop). What I want, of course, is to see progress along the way.
The technique in this book was supposed to help with this.
I would appreciate any help.
Here's the code for the special thread class which uses the EventQueue.InvokeLater method:
==============================================
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LabelUpdater extends Thread
{
private JTextField TextField;
private String displayString;
public LabelUpdater()
{
}
public LabelUpdater(JTextField theTextField)
{
TextField = theTextField;
}
public LabelUpdater(JTextField theTextFieldPassed,
String displayString)
{
TextField = theTextFieldPassed;
this.displayString = displayString;
}
public void run()
{
try
{
while (!interrupted())
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
for (int x =1; x<100000; x++)
TextField.setText("Current Iteration is: " + x);
}
});
Thread.sleep(1);
}
}
catch (InterruptedException exception) {}
}
}
===========================================
Here's the button's actionPerformed() method which sets up this class:
===========================================

new LabelUpdater(jTextField_Status).start();
=====================================
All I'm trying to do is to update the JTextField in a loop. Since this doesn't work without another thread, combined with the Swing "issues" trying to do this, I tried to use this code.
Can anybody see what's missing?
Thanks much.
Mike.
 
Chantal Ackermann
Ranch Hand
Posts: 508
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi,
I replied to your earlier posting as well.
I find it strange that the iterations are done inside the eventqueue thread. I would prefer to do all non-painting outside and only the real painting inside the eventqueue (that is the setText call).
if you want to set the text at a certain time you have to use invokeAndWait. if you use invokeLater you cant be sure when setText will get called ("sometimes later on").
I'd recommend to start your backend work inside its thread and call a thread safe method of its controller class from this thread that will delegate the ui update to the frontend class. to actually update the textfield, use EventQueue.invokeAndWait or SwingUtilities.invokeAndWait (same thing). (although setText should be thread safe??)
you achieve thread safety of a method by making it synchronized or (better?) running its non-thread-safe impl part inside a synchronized block:

what I am doing in my interfaces to notify the ui classes from some change is: I make the controller class listen to the backend class. the backend class fires an event when some value changed. thus, the backend class doesn't need to know about any other class. this mechanism has to be made thread safe as well. but this is just another implementation alternative.
hope I didn't confuse you
c
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!