问题描述
我正在使用一个线程定期运行三秒钟的背景动画.
我从用Swing编写的Thread Demo示例中修改了有问题的代码,并使用了它替代了使用线程和任务的不太有效的早期版本.
I'm using a thread to periodically run a three second background animation.
I adapted the code in question from a Thread Demo example written in Swing and usedit to replace a not quite working earlier version that used both a thread and a task.
播放视频或播放动画时,我的程序停止/暂停线程并在结束视频或动画时开始一个新线程.这似乎没有任何缺点,这就是为什么我不知道为什么以前的JavaFX搜索没有出现的原因与我正在使用的解决方案类似的解决方案.似乎是一种相当直接的跑步方法简短的背景动画.
My program stops/suspends the thread when either playing a video or running an animationand starts a new thread when ending the video or animation. This seems to work withoutany downside which is why I'm puzzled why my earlier JavaFX searches hadn't turned upa similar solution to the one I'm using. It seems a rather direct approach for runningshort, simple background animations.
我在哪里出错呢?我想念什么?我将如何重写此代码同时使用线程和任务还是需要?
Where am I going wrong with this? What am I missing? How would I rewrite this codeusing both a Thread and a Task or do I need to?
我应该添加-while和run语句与原始语句基本保持不变对Swing代码的唯一重要补充是添加thread.setDaemon(true)进入startThread().
I should add - the while and run statements are virtually unchanged from the originaland the only significant addition to the Swing code was to add thread.setDaemon( true )to startThread().
播客侦听器.
// background thread
class BackGround extends Thread {
@Override
public void run() {
while ( suspend.getValue() == false ) {
try {
int r = shared.randInt( 5, 10 );
Thread.sleep( r * 1000 );
} catch ( InterruptedException e ) {
// do nothing
}
if ( suspend.getValue() == false ) {
Platform.runLater( () -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt( 0, g );
gradientColor.set( shared.cssGradients[g] );
Boolean bif = shared.updatePanes( shared.cssGradients[g],
leftPane, rightPane );
});
}
}
}
} // class background
// start thread
public synchronized void startThread() {
thread = new BackGround(); // Thread thread ...defined elsewhere
thread.setDaemon( true );
thread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
推荐答案
Task
类对JavaFX有用的原因是它提供了许多回调,例如succeeded()
,failed()
或cancelled()
和方法像updateProgress()
和updateMessage()
这样将在JavaFX Application线程中运行,因此无需使用Platform.runLater( () -> { ... });
即可更新UI.这使Task
类成为执行后台任务(如下载数据或长时间运行的计算)的理想选择.
The reason the Task
class is useful for JavaFX is that it provides a number of callbacks like succeeded()
, failed()
or cancelled()
and methods like updateProgress()
and updateMessage()
that will run in the JavaFX Application thread and therefore let you update the UI without Platform.runLater( () -> { ... });
This makes the Task
class a perfect choice for doing background tasks like downloading data or long running computations.
但是,由于您的线程只是在没有真正完成其工作的情况下连续运行,因此似乎不需要使用Task
可以通过简单的Thread
为您提供的任何其他功能.
However, since your thread simply runs continuously without ever really finishing its work, it doesn't seem that you would need any of the additional functionality a Task
would provide you with over a simple Thread
.
仍然,如果您真的想将代码转换为使用Task
,它将看起来像这样:
Still, if you really wanted to convert your code to use a Task
, it would look just like this:
class BackGround extends Task<Void> {
@Override
protected Void call() throws Exception {
while (suspend.getValue() == false) {
try {
int r = shared.randInt(5, 10);
Thread.sleep(r * 1000);
} catch (InterruptedException e) {
// do nothing
}
if (suspend.getValue() == false) {
Platform.runLater(() -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g],
leftPane, rightPane);
});
}
}
return null;
}
}
// start thread
public synchronized void startThread() {
Task<Void> bg = new BackGround();
Thread taskThread = new Thread(bg);
taskThread.setDaemon(true);
taskThread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
如您所见,它确实对您没有任何影响,因为您不需要Thread
不能给您的任何东西.但是,如果您想与UI线程进行更紧密的通信,例如显示进度条或显示状态更新,然后Task
将为您提供执行此操作的工具.
As you see, it really doesn't make a difference for you, as you don't need anything that a Thread
couldn't give you. If however you wanted to have closer communication with the UI thread, e.g. showing a progress bar or showing status updates, then a Task
would give you the tools to do that.
我想也值得一提的是,Timeline
的使用非常适合触发动画.看起来像这样:
I guess its also worth mentioning that the use of a Timeline
would be quite elegant for triggering your animations. It would look somewhat like this:
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g], leftPane, rightPane);
}
}
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
handle()
方法中的代码在JavaFX Application线程中每秒运行一次.不幸的是,这只能让您设置两次执行之间的固定时间,而您似乎想每次都等待随机的时间.
The code inside the handle()
method is run every second in the JavaFX Application thread. Unfortunately this only lets you set a fixed time between executions, while you seem to want to wait a random amount of time each time.
TL; DR:可以使用Thread
,因为在用例中不需要Task
的其他功能.
TL;DR: Using a Thread
is ok, because you don't need the additional functionalities of a Task
in your use case.
这篇关于当线程可以完成任务时,我是否需要使用JavaFX中的线程和任务在后台运行某些程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!