Swing, tail -f and threading

F

Frank D. Greco

I'm trying to capture the stdout (and stderr) of an external program
and show the output in a Swing JTextArea.

For most short-running things like 'grep', 'cat'..., its fairly
straightforward. But I'm having a little bit of difficulty with
programs that run for a long time, namely 'tail -f'.

Since 'tail -f foo' basically runs until you kill it, I'm assuming
I need to wrap my JTextArea extended component (which I call 'FileWatcher')
with a Thread/Runnable. This should allow me to instantiate a bunch of
them in a nice front end that watches a bunch of logfiles.

But I'm having problems when the objects are put into a JFrame. Nothing
is rendered properly (1.4.2)... actually the JFrame is blank. But I
get the output correctly since I also write it out to stdout in my console.

Anyone have any suggestions? Should I thread my component externally, i.e.,
in my JFrame when I instantiate my FileWatcher or should I put the thread
"inside" of it, i.e., right before I Process.exec() the external program?
I've tried both but with the same result.

Any tips or URL refs are appreciated.

Frank G.
+==========================================+
| Crossroads Technologies Inc. |
| www.CrossroadsTech dot com |
| fgreco at REMOVE!cross!roads!tech!dot!com|
+=========================================+
 
H

Hung Huynh

Frank D. Greco said:
I'm trying to capture the stdout (and stderr) of an external program
and show the output in a Swing JTextArea.

For most short-running things like 'grep', 'cat'..., its fairly
straightforward. But I'm having a little bit of difficulty with
programs that run for a long time, namely 'tail -f'.

Since 'tail -f foo' basically runs until you kill it, I'm assuming
I need to wrap my JTextArea extended component (which I call 'FileWatcher')
with a Thread/Runnable. This should allow me to instantiate a bunch of
them in a nice front end that watches a bunch of logfiles.

But I'm having problems when the objects are put into a JFrame. Nothing
is rendered properly (1.4.2)... actually the JFrame is blank. But I
get the output correctly since I also write it out to stdout in my console.

Anyone have any suggestions? Should I thread my component externally, i.e.,
in my JFrame when I instantiate my FileWatcher or should I put the thread
"inside" of it, i.e., right before I Process.exec() the external program?
I've tried both but with the same result.

Any tips or URL refs are appreciated.

Frank G.
+==========================================+
| Crossroads Technologies Inc. |
| www.CrossroadsTech dot com |
| fgreco at REMOVE!cross!roads!tech!dot!com|
+=========================================+

Hi,

The code that update your JTextArea when you have new data should be in the
event thread, which must be used via SwingUtilities.invokeLater()

SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// update your jtextarea here
}
});

Hung-
 
F

Frank D. Greco

The code that update your JTextArea when you have new data should be in the
event thread, which must be used via SwingUtilities.invokeLater()

SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// update your jtextarea here
}
});


I've tried this approach but with no luck. This is what I have:

SwingUtilities.invokeLater(
new Runnable() {
public void run() {
try{
while ( (str = in.readLine()) != null ) {
out.println(str); // debugging

append(str);
append("\n");

setCaretPosition(getDocument().getLength());
}

} catch (IOException ix) {
d.trace(1, "Cannot view output of Process stdout");
}
}
}
);

The exec() seems to block when running "tail -f", so I thought the
threading should wrap the exec(), but that doesn't work either.

Any other suggestions are appreciated.

Frank G.
+==========================================+
| Crossroads Technologies Inc. |
| www.CrossroadsTech dot com |
| fgreco at REMOVE!cross!roads!tech!dot!com|
+=========================================+
 
T

Thomas Weidenfeller

Frank said:
I've tried this approach but with no luck. This is what I have:

A couple of things:


0. As mentioned a thousand times in this newsgroup, please provide
complete (has a main(), compiles, runs), small source code, not
snippets. On reason: See next point

The exec() seems to block when running "tail -f", so I thought the
threading should wrap the exec(), but that doesn't work either.

1. You don't show the way you run exec(). It might well be that you
block something there. You would at least have:

- a thread to read from stdout of the external program

- another thread to read from stderr of the external program
(very popular to forget this)

And if you provide input:

- thread nbr. three, if you don't want to block your current
thread

Also:
- possibly a waitFor() in your current thread so you get
informed when the external program terminates.

SwingUtilities.invokeLater(
new Runnable() {
public void run() {
try{
while ( (str = in.readLine()) != null ) {
out.println(str); // debugging

append(str);
append("\n");

setCaretPosition(getDocument().getLength());
}

} catch (IOException ix) {
d.trace(1, "Cannot view output of Process stdout");
}
}
}
);

2. This is doomed to block the EDT. What you are in fact doing is you
schedule one callback on the EDT (your Runnable). The run() method gets
at some point in time executed on the EDT. So your while() loop starts
running in the EDT. You while() loop runs "endlessly", effectively
blocking the EDT for every.

class TextAreaUpdater implements Runnable {
JTextArea ta;
String line;

public TextAreaUpdater(JTextArea ta, String line) {
this.ta = ta;
this.line = line;
}

public void run() {
ta.append(line);
:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top