我正在尝试使用javafx同时执行多个倒计时器。目前使用多线程。现在我试图在标签上打印定时器,以便在屏幕上显示,但无法这样做因为我无法访问控制器类来打印它。如何使用我的线程类在标签上实现打印计时器值。我的计时器值应该打印在gridpane中的标签中,所以我从控制器类中获取约束,然后相应地打印。
package tabapplication;
import java.util.Timer;
import java.util.TimerTask;
import tabapplication.TabApplication;
import tabapplication.FXMLDocumentController;
class Rdt implements Runnable {
private Thread t;
private String threadName;
Rdt( String name){
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
try {
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int s = 60;
int m=30;
public void run() {
s--;
if(s<0 && m>0)
{m--;
s=59;
}
if(s<10)
{ System.out.println(Integer.toString(m)+":"+0+Integer.toString(s)); }
else
{System.out.println(Integer.toString(m)+":"+Integer.toString(s));}
if(m==0 && s==0)
timer.cancel();
}
}, 0, 10);
Thread.sleep(50);
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
public static void main(String args[]) {
Rdt R1 = new Rdt( "Thread-1");
Thread obj1=new Thread(R1);
obj1.start();
Rdt R2 = new Rdt( "Thread-2");
Thread obj2=new Thread(R2);
obj2.start();
}
}
答案 0 :(得分:1)
为Rdt
类提供一个回调函数,以便在它代表更改时执行。这可以是Consumer<String>
的形式,例如:
class Rdt implements Runnable {
private Thread t;
private String threadName;
private Consumer<String> callback ;
Rdt( String name, Consumer<String> callback){
threadName = name;
System.out.println("Creating " + threadName );
this.callback = callback ;
}
public void run() {
System.out.println("Running " + threadName );
try {
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int s = 60;
int m=30;
public void run() {
s--;
if(s<0 && m>0)
{m--;
s=59;
}
if(s<10)
{ callback.accept(Integer.toString(m)+":"+0+Integer.toString(s)); }
else
{callback.accept(Integer.toString(m)+":"+Integer.toString(s));}
if(m==0 && s==0)
timer.cancel();
}
}, 0, 10);
Thread.sleep(50);
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
// ...
}
现在,您可以从控制器类中启动计时器:
public class Controller {
@FXML
private Label timerLabel ;
@FXML
private void startTimer() {
Rdt timer = new Rdt("Timer-1", timerLabel::setText);
timer.run();
}
}
一些旁白:
Timer
类已经为您创建了一个后台线程,因此这将在后台线程中运行,而不会显式创建一个。你真的在很多地方重新发明轮子。例如,标准库已经有一个Duration
class,它可以用来表示分钟和秒,并且已经为你实现了所有的算术运算。考虑:
public class Rdt {
private String name ;
private Consumer<Duration> callback ;
private Duration time ;
public Rdt(String name, Consumer<Duration> callback) {
this.name = name ;
this.callback = callback ;
}
public void startTimer() {
Timer timer = new Timer();
time = Duration.ofMinutes(30);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
time = time.minusSeconds(1);
callback.accept(time);
if (time.isZero()) {
timer.cancel();
}
}
}, 0, 10);
}
}
同样地,DateTimeFormatter
类知道如何将时间格式化为字符串,所以从控制器中你可以做到:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("mm:ss");
Rdt timer = new Rdt("Timer-1", time -> timerLabel.setText(formatter.format(time)));
timer.start();