File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes How to update JTextField from child thread? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "How to update JTextField from child thread?" Watch "How to update JTextField from child thread?" New topic
Author

How to update JTextField from child thread?

Siegfried Heintze
Ranch Hand

Joined: Aug 11, 2000
Posts: 381
I'm trying to run the sample code in "A Tutorial Java 6 New Features" by Budi
Kurniawan page 107. The code for the book is available at
http://books.brainysoftware.com/download/jdk6Samples.zip.

I want to learn how to updated a component, such as a JtextField or JTextArea from a child thread that is different from EDT (event dispatching thread).

Budi's example is not working for me: it does not update the text area!

Can someone kindly point me to a simple example that works?

Also, what was the strategy for doing this prior to Java 6?

Thanks,
Siegfried
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Siegfried Heintze:
I'm trying to run the sample code in "A Tutorial Java 6 New Features" by Budi Kurniawan page 107. The code for the book is available at
http://books.brainysoftware.com/download/jdk6Samples.zip.

I want to learn how to [update] a component, such as a JtextField or JTextArea from a child thread that is different from EDT (event dispatching thread).

Budi's example is not working for me: it does not update the text area!

Can someone kindly point me to a simple example that works?


I don't have access to that book, nor do you mention which of the hundred or so examples in that zip archive you are asking about, so it's hard to say much.

I will point out that JTextField and JTextArea have several fields that are explicitly documented to be thread-safe, including setText(), replaceSelection(), insert(), and append(). I don't know what Kurniawan's example is doing, but you may call these methods from any thread, EDT or not.

[edit: typo]
[ October 24, 2007: Message edited by: Brian Cole ]

bitguru blog
Siegfried Heintze
Ranch Hand

Joined: Aug 11, 2000
Posts: 381

I will point out that JTextField and JTextArea have several fields that are explicitly documented to be thread-safe, including setText(), replaceSelection(), insert(), and append(). I don't know what Kurniawan's example is doing, but you may call these methods from any thread, EDT or not.

Oh really? So does this mean that Budi's code is overkill? When is it necessary to extend SwingWorker? Since Budi is using append and I see that append is not thread safe, then it looks to me like Budi's app would be a legit use of SwingWorker if it worked (it does not).

Are there any other criteria for choosing to extend SwingWorker?

Thanks!
Siegfried

Here is Budi's code:

#!/bin/bash
cat <<EOF0000000000 >CounterTask.java
package swingworker;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class CounterTask extends SwingWorker<Integer, Integer> {
private static final int DELAY = 1000;
private JTextArea textArea;

// A calling application must pass a JTextArea
public CounterTask(JTextArea textArea) {
this.textArea = textArea;
}

@Override
protected Integer doInBackground() throws Exception {
int i = 0;
int count = 10;
while (! isCancelled() && i < count) {
i++;
publish(new Integer[] {i});
setProgress(count * i / count);
Thread.sleep(DELAY);
}

return count;
}

// @Override
protected void process(Integer... chunks) {
for (int i : chunks)
textArea.append(i + "\n");
}

@Override
protected void done() {
if (isCancelled())
textArea.append("Cancelled !");
else
textArea.append("Done !");
}
}

EOF0000000000
cat <<EOF0000000000 >SwingWorkerDemo.java
// This does not run correctly for me. Wed Oct 24 11:49:16 2007

/*
* Begin commands to execute this file using Java with bash
* CLASSPATH=.
* javac -g *.java
* cd ../
* javaw swingworker.SwingWorkerDemo
* cd swingworker/
* rm *.class
* End commands to execute this file using Java with bash
*
*/



package swingworker;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class SwingWorkerDemo {
private static void constructGUI() {
// Text area that displays results
JTextArea textArea = new JTextArea(10, 20);

// Progress bar displaying the progress of the
// time-consuming task
final JProgressBar progressBar = new JProgressBar(0, 10);

final CounterTask task = new CounterTask(textArea);
task.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});

// Start button
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
task.execute();
}
});

// Cancel button
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
task.cancel(true);
}
});

JPanel buttonPanel = new JPanel();
buttonPanel.add(startButton);
buttonPanel.add(cancelButton);

JPanel cp = new JPanel();
LayoutManager layout = new BoxLayout(cp, BoxLayout.Y_AXIS);
cp.setLayout(layout);
cp.add(buttonPanel);
cp.add(new JScrollPane(textArea));
cp.add(progressBar);

JFrame frame = new JFrame("SwingWorker Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(cp);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
constructGUI();
}
});
}
}

EOF0000000000
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Siegfried Heintze:

Oh really? So does this mean that Budi's code is overkill? When is it necessary to extend SwingWorker? Since Budi is using append and I see that append is not thread safe, then it looks to me like Budi's app would be a legit use of SwingWorker if it worked (it does not).

Are there any other criteria for choosing to extend SwingWorker?

Thanks!
Siegfried

Here is Budi's code:

import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class CounterTask extends SwingWorker<Integer, Integer> {
private static final int DELAY = 1000;
private JTextArea textArea;

// A calling application must pass a JTextArea
public CounterTask(JTextArea textArea) {
this.textArea = textArea;
}

@Override
protected Integer doInBackground() throws Exception {
int i = 0;
int count = 10;
while (! isCancelled() && i < count) {
i++;
publish(new Integer[] {i});
setProgress(count * i / count);
Thread.sleep(DELAY);
}

return count;
}

// @Override
protected void process(Integer... chunks) {
for (int i : chunks)
textArea.append(i + "\n");
}


There are two issues here. The first is why doesn't the code work and the second is why use SwingWorker.

A good clue to the former is that the @Override annotation on process() is commented out. If you want the call to publish() to do anything, you need to override process(). There are two ways to fix this.

fix 1: Just call textArea.append(i + "\n") directly instead of publish() in doInBackground(). This is ok because append() is one of those methods that has been documented to be thread-safe.

fix 2: Change the signature from process(Integer... chunks) to process(java.util.List<Integer> chunks) so that it actually overrides. This is obviously what the author of the example intended to do. If it was published in a book, then I bet this fix is listed in the errata.


Ok, on to the second issue.

I wouldn't say that using SwingWorker here is overkill. You don't want your GUI to freeze for 10 seconds, so you want to launch another thread somehow. You could roll your own thread instead of using SwingWorker (but be careful because JProgressBar.setValue() has not been documented to be thread-safe) but SwingWorker is there (starting with jdk6) so why not use it?
Siegfried Heintze
Ranch Hand

Joined: Aug 11, 2000
Posts: 381
Ah hah! Progress! Thanks!

OK, I added the comment. When I try to compile the original code I get:



Can anyone help me with the resolution to this?
Thanks,
Siegfried
Siegfried Heintze
Ranch Hand

Joined: Aug 11, 2000
Posts: 381
Woops, ignore that last message! It works!
Thanks!
Siegfried
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How to update JTextField from child thread?
 
Similar Threads
Struts Design and Programming by Budi Kurniawan
Struts 2
Wanted: Sample JDBC 4 with SQL Annotation
How can I update a JTextField in threaded code?
Which Java do I download?