I have a Runnable that reads Console output from an externally called exe (see below) and writes it to both a log file and a JTextArea.
But my Runnable doesn't show the Console output in the JTextArea until the exe completely finishes. How do I get it to print Console output as it happens?
Short Concise Code Example below:
//Main
import java.awt.*;
import java.io.IOException;
import javax.swing.*;
public class Example extends JFrame {
private static final long serialVersionUID = 1L;
public static int maxX, maxY;
public static JTextArea ta = new JTextArea(20, 60);//For LOG display window
public static void main(String args[] ) throws IOException
{
new Example();
}
public Example() {
this.setTitle("Example");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//MAIN Panel
final JPanel main = new JPanel();
JButton RunButton = button.run(main);
main.add(RunButton);
Container container = getContentPane();
container.add(main);
this.pack();
this.setVisible(true);
}
}
//Button Action Listener
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
public class button {
public static JButton run( final JPanel parent ) {
JButton RunButton = new JButton();
RunButton.setText("Start!");
RunButton.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent event)
{
try
{
//Set up LOG Display
JDialog dialog = new JDialog((JFrame)null, "Working...");
JPanel temp_panel = new JPanel();
temp_panel.add(new JScrollPane(Example.ta));
dialog.getContentPane().add(temp_panel);
dialog.pack();
dialog.setVisible(true);
//Build the Command
ArrayList<String> command = new ArrayList<String>();
command.add("ping");
command.add("127.0.0.1");
//Start the process
Process p = new ProcessBuilder(command).start();
//Starts LOG display capture in separate thread
SwingUtilities.invokeLater(new execute(p));
//Wait for call to complete
p.waitFor();
}
catch(Exception err)
{
JOptionPane.showMessageDialog( parent, "Error Executing Run!", "Warning", JOptionPane.ERROR_MESSAGE );
}
}//end ActionPerformed
});
return RunButton;
}
}
//Runnable
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class execute implements Runnable {
String line;
Process p;
public execute ( Process process ) {
p = process;
}
public void run() {
try {
//Read Process Stream Output and write to LOG file
BufferedReader is = new BufferedReader( new InputStreamReader(p.getInputStream()));
while ( (line = is.readLine()) != null ) {
Example.ta.append(line + "\n");
}
System.out.flush();
} catch(Exception ex) { ex.printStackTrace(); }
}
}
The problem was not that the thread wasn't capturing the data, it was the JTextArea just not refreshing. repaint()
, revalidate()
, and updateUI()
did not refresh the JTextArea, but the following did:
Example.ta.update(Example.ta.getGraphics());