multithreading - JavaFX MediaPlayer - 更新标签以显示线程/任务中的“当前时间”
问题描述
我对 java &generell 编程很陌生。
我有一个小组练习,我们必须编写一个媒体播放器,它应该能够播放音乐文件(不是视频)和 JavaFX 中的其他功能,现在我正在研究“时间滑块”和“总持续时间”和“当前时间”
大多数这些东西都在起作用。我的问题实际上是当前时间,因为我让它在一个while循环中运行。所以程序没有冻结,我发现我必须创建一个任务/线程。持续时间滑块工作正常,更改滑块效果很好。所以用户可以看到他的歌曲有多远,他甚至可以选择他想跳到的时间。
主要问题是更新当前时间。
如果我点击“播放”,则计算总持续时间并调用此代码:
mp.currentTimeProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov)
{
updatesValues();
}
});
之后立即调用此方法。
String setCurrentTime = "0:00";
private void updatesValues(){
Runnable r = new Runnable() {
public void run() {
while (isPlaying) {
//System.out.println(mp.getCurrentTime().toMinutes()); // Debug
String setCurrentTime = "0:00";
private void updatesValues(){
Runnable r = new Runnable() {
public void run() {
while (isPlaying) {
//System.out.println(mp.getCurrentTime().toMinutes()); // Debug
String currentTime = "";
int timeCurrentTime = (int) (100 * mp.getCurrentTime().toMinutes());
int hourCurrentTime = timeCurrentTime / 3600;
int minCurrentTime = timeCurrentTime / 100;
int secCurrentTime = 60 * (timeCurrentTime % 100);
if (hourCurrentTime == 0) {
if(secCurrentTime < (60 * (timeCurrentTime % 100))){
System.out.printf("%.2s:0%.1s \n", minCurrentTime, secCurrentTime);
setCurrentTime = currentTime.format("%.2s:0%.1s",minCurrentTime,secCurrentTime);
}else{
System.out.printf("%.2s:%.2s \n", minCurrentTime, secCurrentTime);
setCurrentTime = currentTime.format("%.2s:%.2s",minCurrentTime,secCurrentTime);
}
} else {
if(secCurrentTime < (60 * (timeCurrentTime % 100))){
System.out.printf("%.2:%.2s:0%.1s \n", hourCurrentTime,minCurrentTime, secCurrentTime);
setCurrentTime = currentTime.format("%.2s%.2s:0%.1s",hourCurrentTime,minCurrentTime,secCurrentTime);
}else{
System.out.printf("%.2s:%.2s:%.2s \n", hourCurrentTime, minCurrentTime, secCurrentTime);
setCurrentTime = currentTime.format("%.2:%.2s:%.2s",hourCurrentTime,minCurrentTime,secCurrentTime);
}
}
durationSlider.setValue(mp.getCurrentTime().toMillis()/ mp.getTotalDuration().toMillis() * 100);
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
};
displayCurrentTime.setText(setCurrentTime);
new Thread(r).start();
}
Systemout 工作正常。我只是在格式化方面遇到了一些问题。也许还有计算/计算部分。睡眠部分不工作,所以控制台被垃圾邮件(可能是因为毫秒)。它看起来像:0:01 0:01 0:01 0:01 0:01 0:01 0:02 0:02 等等。滑块正在工作并得到更新,但标签“displayCurrentTime”没有
一种解决方法是放置“String setCurrentTime = “0:00”;” 在方法和“displayCurrentTime.setText(setCurrentTime);”之前 最后但在新的“Thread(r).start();”之前
至少它现在可以工作,但看起来并不好。问题只是,时间有时比其他时间更新得更快。示例:1..2..3.4..5.6..7.8.9.0.10.11..12.13..14.15(点是每个值之间的中断)(可能是因为毫秒)
有谁知道我该如何解决这个问题,或者可能以另一种方式更新标签?
解决方案
您的代码中有一些错误。
durationSlider
您从后台线程更新 的值。JavaFX 是单线程的,只能从JavaFX 应用程序线程访问 GUI 。- 您可以
Platform.runLater
在此处使用(但有更好的选择,请参见第 4 点)。
- 您可以
- 该
setCurrentTime
字段不是,但您正在后台线程上写入它并在JavaFX Application Threadvolatile
上读取它。这意味着一个线程的更新不能保证被另一个线程看到。- 这也可能是一个问题,
isPlaying
但您没有显示它的声明。
- 这也可能是一个问题,
- 每次
updateValues()
调用你都会启动一个新线程!!- 由于该
MediaPlayer.currentTime
属性通常会失效,因此您最终会得到很多线程。
- 由于该
- 您首先使用后台线程。
- 不使用后台线程否定了前三点。
- 你用
currentTime.format(...)
. 该String.format
方法是静态的,最好这样调用它:String.format(...)
.- 这使您的代码更清晰。事实上,人们可能会认为它
format
是一个实例方法。
- 这使您的代码更清晰。事实上,人们可能会认为它
关于第 4 点:
无需使用后台线程来更新durationSlider
或displayCurrentTime
。的currentTime
属性MediaPlayer
将在媒体播放时自动更新(并每次通知任何听众)。这些更新将发生在JavaFX 应用程序线程上。您需要做的就是更新侦听器内的 UI;由于计算并不昂贵,因此可以在JavaFX Application Thread上进行计算。
mp.currentTimeProperty().addListener((observable, oldTime, newTime) -> {
durationSlider.setValue(newTime.toMillis() / mp.getTotalDuration().toMillis() * 100);
String formattedTime = ...; // your computations
displayCurrentTime.setText(formattedTime);
});
上面的代码使用 ajavafx.beans.value.ChangeListener
而不是InvalidationListener
. 它还使用 lambda;但是,如果您不想使用 lambdas(或还不了解它们),则该代码等效于:
mp.currentTimeProperty().addListener(new ChangeListener<>() {
@Override
public void changed(ObservableValue<? extends Duration> observable,
Duration oldTime, Duration newTime) {
durationSlider.setValue(newTime.toMillis() / mp.getTotalDuration().toMillis() * 100);
String formattedTime = ...; // your computations
displayCurrentTime.setText(formattedTime);
}
});
推荐阅读
- python - how to convert a multiple python files into one ipynb file?
- android - Transparent Toolbar is Gray
- r - How to write R code for mcmc of a changepoint logistic model
- node.js - Firebase Cloud Functions 在实时数据库 onCreate 上获取数据
- http - FLUTTER How to implement Digest Authentification
- timeout - Axios - ERR_EMPTY_RESPONSE on long lasting requests
- python - 给定时间原点,如何将日期时间从十进制转换为“%y-%m-%d %H:%M:%S”?
- angular - How do I fill in an input using javascript on an angular site?
- indexing - 能否以编程方式构建 Sitecore Lucene 索引?
- swift - Apple“延迟照明”在我的 MacBook Pro 2018 和 Vega 20 上都是绿色的