javax.swing.JFrame setText() in a loop? + intentional delay?
-
22-10-2019 - |
Question
I am very new to Java (only been using it for about a week) and I'm working on a store simulator. Basically I just want to get basic things done right now like having a time until closing and a time since opening variable displayed on the screen.
I have made the following functions in my Simulation extends javax.swing.JFrame class :
public void incOpenTime() {
timeOpen++;
int hours = timeOpen / 3600;
int minutes = (timeOpen % 3600) / 60;
int seconds = (timeOpen % 3600) % 60;
this.openTime.setText((hours < 10 ? "0" : "") + hours
+ ":" + (minutes < 10 ? "0" : "") + minutes
+ ":" + (seconds < 10 ? "0" : "") + seconds);
decTimeLeft();
}
public void decTimeLeft() {
int remainingTime = 28800 - timeOpen;
int hours = remainingTime / 3600;
int minutes = (remainingTime % 3600) / 60;
int seconds = (remainingTime % 3600) % 60;
this.timeLeft.setText((hours < 10 ? "0" : "") + hours
+ ":" + (minutes < 10 ? "0" : "") + minutes
+ ":" + (seconds < 10 ? "0" : "") + seconds);
}
The openTime and timeLeft variables using the setText() method are part of the GUI itself.
In main, I call incOpenTime like so:
while(this.timeOpen < 28800)
{
incOpenTime();
}
First off, when I run this it basically just goes through the loop and outputs only the last time to the screen. How would I make it so the times are constantly changing?
Secondly, I would like to delay it slightly...maybe about 1ms per second so the simulation runs slower and other data being output to the screen (later) is more readable. I've tried Thread.sleep(1); in the loop but it doesn't display the numbers as they are changed.
Please help.
Thanks
EDIT:
Here's what I did to get it working. In main:
timer = new Timer();
for(int i=1; i<= 28800; i++)
{
timer.schedule(new task(), 1*i);
}
Made a new class:
class task extends TimerTask {
@Override
public void run() {
incOpenTime();
}
}
Solution
You need a java.util.Timer
Edit: As this is the accepted answer, it is important to note that the TimerTask
should execute its Runnable
on the event dispatch thread. The correct variation of this approach is noted in @mKorbel's answer. There's a short example below and a more elaborate one here. A somewhat simpler approach, suggested by @Hovercraft, is seen here.
class Task extends TimerTask {
@Override
public void run() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
incOpenTime();
}
});
}
}
OTHER TIPS
javax.swing.Timer
may be a good choice, as "the action event handlers for Timers
execute on … the event-dispatching thread." There's an example here.
your output from BackGroung Task or Thread to the GUI isn't correctly posted to the EDT,
you have to wrap any of output to the GUI (from BackGroung Task or Thread) to the
invokeLater()
if method could be Synchronized then
invokeAndWait()
please read more about Concurency in Swing