Simple way to show quickly-changing values

I feel like a bit of a noob asking this; I’m trying to show a few quickly-changing values in a window (just a simple JFrame with a TextArea). Unfortunately, they change very quickly (i.e. 50 times a second), which cause the text to flicker to the point of being unreadable. It’s only for a bit of debugging, so I was trying to do this simply, but can’t seem to find an easy solution.

I’ve tried directly setting the text in the TextArea, and also using invokeLater(), but neither work well:-

SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					textArea.setText(str);
				}
			});

Does anyone have a solution, or a simple way of just showing some quickly-changing debugging output in a window? Thanks!

I’m not too sure about this, but I think you have to use SwingUtilities.invokeAndWait - because otherwise the String str could change be changed by your non-swing thread while the last runnable is still being executed on the EDT.


final String refCopy = str; // just in case 'str' was actually a field, and not a local-var
SwingUtilities.invokeLater(new Runnable() {
   public void run() {
      textArea.setText(refCopy);
   }
});

If you only want to view data, you should use a JLabel, not a JTextArea.

You can use a timestamp and test for elapsed time before updating the JLabel.

If this were more than just a test, I’d consider polling the value from the game loop rather than using every change, unless you need to know each step.

For example, for a 2D area used for a virtual Theremin (y-axis = volume, x-axis = pitch) I poll the mouse position from the game loop rather than allow the mouse movement listener to drive the updates. The mouse is restricted to updating local variables which get checked by the game loop for current value. The synthesizer, upon receiving the new values every 16.6 millis or so (60fps), instead of sporadically and in clusters, employs smoothing based on the known time increment between updates. This works well. But of course it may not fit the requirements of your particular needs.

One problem with the invokeLater() approach is you really want to coalesce all these values - there’s no point in running a Runnable that’s setting the text if you already have another Runnable on the queue.

An option might be to pass the strings into a concurrent queue, and drain it within your Runnable, only setting the last available String value (some Runnable will see an empty queue).

Another option, if you know the value is always changing, would be to poll from a Swing Timer.

If you have another thread you want to poll values from that are more complex (or just want to communicate with), it’s also worth implementing an equivalent of invokeLater(). You can call with a Runnable that queries values and posts them back to the EDT. Lock free and asynchronous ftw!

I’d stay away from invokeAndWait() unless you really need it - it’s deadlock prone! Notable that they didn’t implement the same in JavaFX.

Why would using invokeLater() make any difference?

Either set up a function that only changes the text every X times, or change your approach to append the text to the bottom instead of overwriting it completely.

Thanks for all the replies. As suggested by philfrei and KevinWorkMAN, I’ve decided that since I don’t need to see the new values ~50 times a second, I’ll just update the text every second or so. I don’t know why i didn’t think of that before (as is always the case!).