Frame Refresh Thread issue.

Hello again,

Middleware Developer attempting Guis.

Have what appears to be a simple thread issue with the repaint and/or listener threads not performing correctly.

Heres what I did. I made a simple gui. Assigned listeners to buttons etc. In the actionperformed areas I just simply used them to begin a line of executing code. I did NOT start any task specific threads.

This problem is noticeable for me because I am trying to use a ProgressBar. In a hardcoded test of the progress bar I put a button on the gui and when clicked it . It would simply count up from min to max and change its display text. However the gui appears to be dead. meaning that I can drag a window over it and the Frames graphics are skewed and do not return until the task is completed. This makes me feel as if I have used the thread that calls the repaint() or whatever to keep the Gui alive, to do something else.

After reading this Im not sure if I can verbalize enough of what the problem is to get any help.

try 2: I got a gui when I click a button that leads directly to code that needs to be run by that thread my front end goes dead. Should I use different threads or can I start a thread to refresh the front constantly. I figure its just lack of experence that is causing this. So feel free to comment or direct me to the basics of Guis.

Thanks B

[1387 byte] By [braindamageda] at [2007-10-2 8:09:05]
# 1

>

>

> Heres what I did. I made a simple gui. Assigned

> d listeners to buttons etc. In the actionperformed

> areas I just simply used them to begin a line of

> executing code. I did NOT start any task specific

> threads.

Then this is most probably the source of your problem! You are probably doing everything in the event thread which stops it updating the screen.

Do the 'tasks' in a separate thread and then use SwingUtilities.invokeLater() to update the GUI once the thread has done it's work.

P.S. Why did you put so much effort into trying to change the colour of the text in your progress bar when you did not have the fundamentals working?

sabre150a at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for the reply sabre.

I did do everything with the event thread. I am hoping by your reply that means that it should not be done that way. I will try to start off a task thread then update later as you suggested. However with another thread started I would like to make sure that all other threads are listening and the frame is active. Ie if I had a cancel button Id like to be able to click it and fire the event no matter what other threads are doing.

I am hoping that your quote "You are probably doing everything in the event thread which stops it updating the screen" defines the problem. Seems odd that the click event disables the refresh but dont know the way Swing works well enough to say anything.

In response to your question: "Why did you put so much effort into trying to change the colour of the text in your progress bar when you did not have the fundamentals working?" I have the grand total of about 40hrs building Swing GUis over 3 years. This problem came retrospec to the decision to use a ProgressBar. I needed to to change the color to fit given color Scheme. Since I kinda thought that changing the color would be easy, I pursued it. However being very inexperenced in Swing (and AWT for that matter) I am finding the problems as they arise. I first ggot the color Change to work by counting from 1 to 100(blah blah). But I just did this right in the event of a button. So after proving to myself I could change the color of the text. I found this monster. Bottom line is I dont have enough experence.

What would you suggest to become more familiar with key concepts of JFC?

Thanks for the replay

B.

braindamageda at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 3
You might want to look at the SwingWorker class. I'm make good use of this class to ensure my Swing apps stays 'live' and certain animations work well.If you search for SwingWorker in the forum you'll find lots of references
CGriswolda at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 4

Thanks for the suggestion.

I also see the thread that u bumped up that sounds very much to describe what I got going on here. can be found at http://forum.java.sun.com/thread.jspa?threadID=693149&tstart=0

Gonna read the post there and see if I can get lowdown on this this issue than take a look at the SwingWorker class

Thanks for the advice

braindamageda at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 5

Uggg. cant seem to get what i need. Now I cant get the Jprogressbar to refresh. Let me show you what I did in regards to invokeLater call

public void btnCreate_actionPerformed(ActionEvent actionEvent) {

//createMap();

//new Thread(new Runnable(){public void run(){createMap();}}).start();

SwingUtilities.invokeLater(new Runnable(){public void run(){createMap();}});

}

I read the documentation and it appears that It will still use this thread to execute the code after it is "deferred until all pending events have been processed". I did this and after I fired the go button I tried to click a checkbox. It would not click. Which tells me the thread that is supossed to be listening is "doing something else".

Im not sure if I need to use this invokeLater in this case. here is another ******* piece of code that I am trying to use to get the Jprogrees bar to refresh

private void setAndRefreshProgBar(int value) {

//System.out.println("setAndRefreshProgBar called");

jProgressBar1.setValue(value);

Rectangle progressRect = jProgressBar1.getBounds();

progressRect.x = 0;

progressRect.y = 0;

jProgressBar1.paintImmediately(progressRect);

}

Is this right? can I call this homemade method from an independent thread and expect it to update. I am thinking that it should if the thread that repaints the frame will respond to the paintImmediately call.

any comments welcome.

B

braindamageda at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 6

here's sun's JProgressBarDemo - 3 classes put together

run it, see how it works, then modify your code accordingly

(more info in the 3 http links at the top)

//http://java.sun.com/docs/books/tutorial/uiswing/components/example-1dot4/ProgressBarDemo.java

//http://java.sun.com/docs/books/tutorial/uiswing/components/example-1dot4/LongTask.java

//http://java.sun.com/docs/books/tutorial/uiswing/misc/example-1dot4/SwingWorker.java

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.SwingUtilities;

class ProgressBarDemo extends JPanel implements ActionListener {

public final static int ONE_SECOND = 1000;

private JProgressBar progressBar;

private Timer timer;

private JButton startButton;

private LongTask task;

private JTextArea taskOutput;

private String newline = "\n";

public ProgressBarDemo() {

super(new BorderLayout());

task = new LongTask();

startButton = new JButton("Start");

startButton.setActionCommand("start");

startButton.addActionListener(this);

progressBar = new JProgressBar(0, task.getLengthOfTask());

progressBar.setValue(0);

progressBar.setStringPainted(true);

taskOutput = new JTextArea(5, 20);

taskOutput.setMargin(new Insets(5,5,5,5));

taskOutput.setEditable(false);

taskOutput.setCursor(null);

JPanel panel = new JPanel();

panel.add(startButton);

panel.add(progressBar);

add(panel, BorderLayout.PAGE_START);

add(new JScrollPane(taskOutput), BorderLayout.CENTER);

setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

timer = new Timer(ONE_SECOND, new ActionListener() {

public void actionPerformed(ActionEvent evt) {

progressBar.setValue(task.getCurrent());

String s = task.getMessage();

if (s != null) {

taskOutput.append(s + newline);

taskOutput.setCaretPosition(

taskOutput.getDocument().getLength());

}

if (task.isDone()) {

Toolkit.getDefaultToolkit().beep();

timer.stop();

startButton.setEnabled(true);

setCursor(null); //turn off the wait cursor

progressBar.setValue(progressBar.getMinimum());

}

}

});

}

public void actionPerformed(ActionEvent evt) {

startButton.setEnabled(false);

setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

task.go();

timer.start();

}

private static void createAndShowGUI() {

JFrame.setDefaultLookAndFeelDecorated(true);

JFrame frame = new JFrame("ProgressBarDemo");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JComponent newContentPane = new ProgressBarDemo();

newContentPane.setOpaque(true); //content panes must be opaque

frame.setContentPane(newContentPane);

frame.pack();

frame.setVisible(true);

}

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

}

class LongTask {

private int lengthOfTask;

private int current = 0;

private boolean done = false;

private boolean canceled = false;

private String statMessage;

public LongTask() {

lengthOfTask = 1000;

}

public void go() {

final SwingWorker worker = new SwingWorker() {

public Object construct() {

current = 0;

done = false;

canceled = false;

statMessage = null;

return new ActualTask();

}

};

worker.start();

}

public int getLengthOfTask() {

return lengthOfTask;

}

public int getCurrent() {

return current;

}

public void stop() {

canceled = true;

statMessage = null;

}

public boolean isDone() {

return done;

}

public String getMessage() {

return statMessage;

}

class ActualTask {

ActualTask() {

while (!canceled && !done) {

try {

Thread.sleep(1000);

current += Math.random() * 100;

if (current >= lengthOfTask) {

done = true;

current = lengthOfTask;

}

statMessage = "Completed " + current +

" out of " + lengthOfTask + ".";

} catch (InterruptedException e) {

System.out.println("ActualTask interrupted");

}

}

}

}

}

abstract class SwingWorker {

private Object value;

private static class ThreadVar {

private Thread thread;

ThreadVar(Thread t) { thread = t; }

synchronized Thread get() { return thread; }

synchronized void clear() { thread = null; }

}

private ThreadVar threadVar;

protected synchronized Object getValue() {

return value;

}

private synchronized void setValue(Object x) {

value = x;

}

public abstract Object construct();

public void finished() {

}

public void interrupt() {

Thread t = threadVar.get();

if (t != null) {

t.interrupt();

}

threadVar.clear();

}

public Object get() {

while (true) {

Thread t = threadVar.get();

if (t == null) {

return getValue();

}

try {

t.join();

}

catch (InterruptedException e) {

Thread.currentThread().interrupt();

return null;

}

}

}

public SwingWorker() {

final Runnable doFinished = new Runnable() {

public void run() { finished(); }

};

Runnable doConstruct = new Runnable() {

public void run() {

try {

setValue(construct());

}

finally {

threadVar.clear();

}

SwingUtilities.invokeLater(doFinished);

}

};

Thread t = new Thread(doConstruct);

threadVar = new ThreadVar(t);

}

public void start() {

Thread t = threadVar.get();

if (t != null) {

t.start();

}

}

}

Michael_Dunna at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 7
I didn't look at the example code posted but I've had no problem using a progress bar to show the progress of a very CPU intensive task. In the case I'm thinking of the task that the bar is showing the progress of is running in a seperate thread.
FlyingSnaila at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...
# 8

To close this...

I was not familiar with the event disptching thread and what it means to use or not use this thread to do actually work. I have read and now barely understand that I should not use this thread for the actually work. I ended up starting another thread then using a timer to refresh the UI like every 250ms. All ideas I got where from the suggestions from these fourms and the kind peeps that responded.

I found it rather difficult to accomplish this task, this is due to the fact that I had realitivley no experence with Swing. I am still having dificulty with alot of stuff in swing but I think with a little time the patterns and just experence might make this all clear. No onto the next thing (JscrollPanes... grr) look for my post soon if you think you can help in many ways.

ALSO ANY SUGGESTIONS for noob Swing guys would be of great assistance. Any of you Swing masters know of the golden book that makes swing easy to get started with the title would be like gold to me.

Thanks

B.

braindamageda at 2007-7-16 22:04:17 > top of Java-index,Desktop,Core GUI APIs...