此代码示例属于Stopwatch类的一部分,该类属于一个较大的项目的一部分,该更大的项目的目的是成为模仿Android
Clock的桌面gui应用。我具有秒,分钟,小时等标签,这些标签应该从计时器任务内部的无限while循环中更新,而该计时器任务在布尔状态为true时运行。while循环应该实时更新GUI标签。我让计时器任务每毫秒执行一次。为什么我的GUI在程序更新第一个Label后立即挂起,我该如何解决?下面是代码。
static int Milliseconds = 0;
static int Seconds = 0;
static int Minutes = 0;
static int Hours = 0;
static int Days = 0;
static Boolean State = false;
public static void display(){
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle("Timer");
window.setMinWidth(250);
window.setMinHeight(500);
GridPane gp = new GridPane();
Label days = new Label("0");
gp.setConstraints(days, 0,0);
Label hours = new Label("0");
gp.setConstraints(hours, 1,0);
Label minutes = new Label("0");
gp.setConstraints(minutes,2,0);
Label seconds = new Label("0");
gp.setConstraints(seconds,3,0);
Label milliseconds = new Label("0");
gp.setConstraints(milliseconds, 4,0);
//Handler mainHandler = new Handler()
// Task<Void> longRunningTask = new Task<Void>(){}
Timer mt = new Timer();
//Platform.runLater is not updating gui. It hangs the gui instead
TimerTask tm = new TimerTask() {
@Override
public void run() {
Platform.runLater(() -> {
for (; ; ) {
long timebefore = System.currentTimeMillis();
if (State) {
try {
if (Milliseconds > 999) {
Milliseconds = 0;
Seconds++;
}
if (Seconds > 59) {
Milliseconds = 0;
Seconds = 0;
Minutes++;
}
if (Minutes > 59) {
Milliseconds = 0;
Seconds = 0;
Minutes = 0;
Hours++;
}
if (Hours > 23) {
Milliseconds = 0;
Seconds = 0;
Minutes = 0;
Hours = 0;
Days++;
}
milliseconds.setText(" : " + Milliseconds);
Milliseconds++;
seconds.setText(" : " + Seconds);
minutes.setText(" : " + Minutes);
hours.setText(" : " + Hours);
days.setText(" : " + Days);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
};
Button start = new Button("Start");
gp.setConstraints(start, 0,1);
start.setOnAction(event -> {
State = true;
mt.scheduleAtFixedRate(tm, 1,1);
});
Button stop = new Button("Stop");
gp.setConstraints(stop,1,1);
stop.setOnAction(event-> {
State = false;
});
Button restart = new Button("Restart");
gp.setConstraints(restart, 2,1);
restart.setOnAction(event-> {
State = false;
Milliseconds = 0;
Seconds = 0;
Minutes = 0;
Hours = 0;
Days = 0;
});
gp.getChildren().addAll(milliseconds,seconds, minutes, hours, days, start, stop, restart);
Scene scene = new Scene(gp);
window.setScene(scene);
window.showAndWait();
}
public void Start(Timer mt){
}
将Runnable
传递给Platform#runLater(Runnable)
包含一个无限循环。这意味着您在 JavaFX Application
Thread
上执行了无限循环,这就是UI变得无响应的原因。如果FX线程不能自由执行其工作,则无法处理用户生成的事件,并且无法安排渲染“脉冲”。后一点就是为什么即使您setText(...)
不断调用UI也不更新。
如果要继续使用当前方法,解决方法是for (;;)
从Runnable
实现中删除循环。您将设置为TimerTask
每毫秒执行一次,这意味着您要做的就是计算新状态并为每次执行设置一次标签。换句话说,该run()
方法已经“循环”。例如:
TimerTask task = new TimerTask() {
@Override public void run() {
Platform.runLater(() -> {
// calculate new state...
// update labels...
// return (no loop!)
});
}
};
也就是说,没有理由为此使用后台线程。我建议改用JavaFX提供的动画API。它是异步的,但在FX线程上执行,因此更易于实现和推理-
使用多个线程总是更复杂。要执行与当前操作类似的操作,可以使用Timeline
或PauseTransition
代替java.util.Timer
。在JavaFX的周期性后台任务
Q&A给出了使用动画用于此目的的一些很好的例子。
就个人而言,我将使用AnimationTimer
来实现秒表。这是一个例子:
import java.util.concurrent.TimeUnit;
import javafx.animation.AnimationTimer;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
public class Stopwatch {
private static long toMillis(long nanos) {
return TimeUnit.NANOSECONDS.toMillis(nanos);
}
// value is in milliseconds
private final ReadOnlyLongWrapper elapsedTime = new ReadOnlyLongWrapper(this, "elapsedTime");
private void setElapsedTime(long elapsedTime) { this.elapsedTime.set(elapsedTime); }
public final long getElapsedTime() { return elapsedTime.get(); }
public final ReadOnlyLongProperty elapsedTimeProperty() { return elapsedTime.getReadOnlyProperty(); }
private final ReadOnlyBooleanWrapper running = new ReadOnlyBooleanWrapper(this, "running");
private void setRunning(boolean running) { this.running.set(running); }
public final boolean isRunning() { return running.get(); }
public final ReadOnlyBooleanProperty runningProperty() { return running.getReadOnlyProperty(); }
private final Timer timer = new Timer();
public void start() {
if (!isRunning()) {
timer.start();
setRunning(true);
}
}
public void stop() {
if (isRunning()) {
timer.pause();
setRunning(false);
}
}
public void reset() {
timer.stopAndReset();
setElapsedTime(0);
setRunning(false);
}
private class Timer extends AnimationTimer {
private long originTime = Long.MIN_VALUE;
private long pauseTime = Long.MIN_VALUE;
private boolean pausing;
@Override
public void handle(long now) {
if (pausing) {
pauseTime = toMillis(now);
pausing = false;
stop();
} else {
if (originTime == Long.MIN_VALUE) {
originTime = toMillis(now);
} else if (pauseTime != Long.MIN_VALUE) {
originTime += toMillis(now) - pauseTime;
pauseTime = Long.MIN_VALUE;
}
setElapsedTime(toMillis(now) - originTime);
}
}
@Override
public void start() {
pausing = false;
super.start();
}
void pause() {
if (originTime != Long.MIN_VALUE) {
pausing = true;
} else {
stop();
}
}
void stopAndReset() {
stop();
originTime = Long.MIN_VALUE;
pauseTime = Long.MIN_VALUE;
pausing = false;
}
}
}
警告: 在AnimationTimer
运行Stopwatch
实例时,无法进行垃圾回收。
上面提供了一个属性,elapsedTime
表示经过的时间(以毫秒为单位)。根据该值,您可以计算自秒表启动以来经过的天,小时,分钟,秒和毫秒的数量。您只需收听属性并在属性更改时更新UI。
问题内容: 我在使用Tkinter和PIL更新标签时遇到了一个“小”问题。 当我按下起 司 按钮时,它应该显示foo2,但是它只显示白色屏幕。有什么建议? 这是我的代码: 问题答案: 好吧,我认为原因是当您按下按钮时。这是因为此行: 应该: 出现这种情况,是因为,等回报。
我有一个标签,这是使用了多次在我的网页。它工作得很好,直到我尝试按Ajax更新标签。结果:只有第一个标签得到更新。这是一个已知的问题吗?我不确定,因为我不能打开JIRA页面:https://issues.apache.org/JIRA/browse/wicket(一直在跳)。我使用的是wicket 7.3.0版本 =>只更新第一个标签。我有一个解决办法,通过添加4个不同的标签实例与相同的文本内容。
问题内容: 我在这段代码上遇到了麻烦。 我正在使用一个随机数启动一个计时器,并且我想每秒倒数一次更新JLabel。但是我还没有弄清楚该怎么做,因为计时器触发的唯一侦听器位于它的末尾(我知道)。 这是代码: 问题答案: 我不太了解您为什么使用随机数的问题,但以下是一些观察结果: 我想每秒钟更新一次带有倒计时的JLabel。 然后,您需要将计时器设置为每秒触发一次。因此,计时器的参数是1000,而不是
问题内容: 我有一个活动,该活动的TabHost包含一组TabSpec,每个TabSpec都有一个listview,其中包含要由该选项卡显示的项目。创建每个TabSpec时,我设置一个图标以显示在选项卡标题中。 TabSpec是通过以下方法创建的,该方法循环创建适当数量的选项卡: 有几个实例,我希望能够更改程序执行过程中每个选项卡中显示的图标。目前,我正在删除所有选项卡,并再次调用上述代码以重新创
我正在尝试使用postman和curl更新Jira标签,但是这两种方法都失败了,错误消息不同。 curl-D--u userName-X PUT--data“{”update:{”labels:[{”add:“new_label”}]}”-H“内容类型:application/json”https://jira-internal.net/rest/api/2/issue/APP-12345 格式输
问题内容: 我正在更新我的Kubernetes容器: 以下是我的service.yaml: 以下是我的deployment.yaml: 第一次可以正常运行,但是在随后的运行中,我的广告连播没有得到更新。 我已经在https://github.com/kubernetes/kubernetes/issues/33664上阅读了建议的解决方法,该方法是: 我能够运行上面的命令,但是它没有为我解决问题。