I have in a jFrame a jLabel that must update its content from the output of shell script. The execution of the shell script is made from a thread in another jFrame in which I store the output in a StringBuilder (public and static):
p = Runtime.getRuntime().exec("testpad -i -c"+can+" -n"+pad+" "+pathFile);
final InputStream inStream = p.getInputStream();
Thread uiThread = new Thread("UIHandler") {
@Override
public void run() {
InputStreamReader reader = new InputStreamReader(inStream);
Scanner scan = new Scanner(reader);
prec=null;
while (scan.hasNextLine()) {
prec=scan.nextLine();
System.out.println(prec);
sbuff.append(prec);
sbuff.append('\n');
}
}
};
uiThread.start();
I update the jLabel (content in a jPannel) when the jPannel is showed:
private void jPanel1ComponentShown(java.awt.event.ComponentEvent evt) {
// TODO add your handling code here:
jLabel2.setText(inizio.sbuff.toString());
}
I think it is a race condition trouble but I put a Thread.sleep() with many second but the conten of jLabel don't update. I am doing this how example:
When I push the jButton the shell script print the output in the rectangle in red , then it opens a new jFrame with the jLabel that it should update but its don't change. Where am I wrong? Thanks.
Looking at the problem description, my guess is that you are trying to update the label before getting the results.
Rather than updating text in component shown callback, try explicitly setting the text after background processing is complete.
There are other problems with your approach like not using swing worker for background tasks, trying to display multiline text in a JLabel (JTextArea will be better suited for this).
It's impossible to 100% as you've not provided any evidence to support how the code is executed, but I'm assuming that when you start the
Thread
, you also open the second frame.This is probably a bad idea. Instead, you could use a
SwingWorker
which will allow you to execute the script in the background, freeing up the UI thread.When the
SwingWorker
completes, you would then create and show the second window passing the result of the script to it...Have a look at Concurrency in Swing and Worker Threads and SwingWorker for more details. I'd also have a look at The Use of Multiple JFrames, Good/Bad Practice? and consider using a
CardLayout
instead, see How to Use CardLayout for more detailsA alternative approach might be to use a Producer-Consumer pattern, where the
SwingWorker
is the producer and we use ainterface
which acts a contract for the consumer. In this way, you UI couldimplement
the consumer contract and be notified when new content was made availableThis means you could start the
SwingWorker
AND setup the new UI at the same time, it also means you don't need to wait for the process to exit before getting output from it.In the above example, we use the
publish
/process
functionality of the worker to synchronise updates to the UI thread, making it safe to update the UI components from.Oh, and unless you wrap the output text in HTML,
JLabel
is probably not your best bet, maybe consider using aJTextArea
instead