Re: setText() is not always updating Jtextfield and Jlabel items
On 26/02/15 20:23, Kevin Nathan wrote:
// Trying new "Motion" routine:
while (clerkFuncs.scaleErr == -2) {
weight = clerkFuncs.readScale(tr);
showMotion(weight);
}
private void showMotion(long wt) {
noteField[1][weightRow].setText(Long.toString(wt));
// noteField[1][weightRow].setText("<html><font
color='red'>Motion</font></html>");
editField[1][weightRow].setText("Motion");
}
This is the problem.
For setText() to work it needs to be invoked by the Event Dispatch Thread
(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)
However, there is also the issue of allowing the EDT to do its work. If you block the thread in a loop then the EDT
never gets a chance to do its work.
Your code above is wrong because it either
1) is not invoked on the EDT
2) is invoked on the EDT and therefore blocks the thread in the while() loop.
The normal way that Swing is used is either by event action, or by explicitly invoking a method on the EDT.
If your code is an action handler invoked on the EDT then it must perform an action and return to allow the EDT to get
on with everything else it has to do. If your code is running on thread other than the EDT it should invoke the
setText() method on the EDT by using SwingUtilities.invokeAndWait() or SwingUtilities.invokeLater(). setText() is one of
those methods which "mostly" works if you use on a non-EDT thread, which may explain why your code appears to work for
other uses of setText(). However, "mostly" is not always, and it's incorrect code because setText() is not thread safe,
and it will likely cause you intermittent and non-reproducable problems when you least expect, or want, them in
production use.
With the code you have, the while loop should not be running on the EDT. The showMotion() method should be. I don't know
how you get to the path of the while loop, but it's probably going to have to be changed. To get the while loop to run
the setText() method on the EDT you use something along the lines of:
final long weight=wt;
SwingUtilties.invokeAndWait(new Runnable() { public void run() {showMotion(weight); }} );
The other, and arguably more elegant solution, is to use a SwingWorker.
Your while loop would go in the doInBackground() method, and publish() the weights. The SwingWorker.process() method
would essentially be your showMotion() method which processes the published weights.
The above link to the Java Swing tutorial should hopefully provide some insight.
Just remember the fundamental issue, Swing is event driven on the EDT.