我对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(点是每个值之间的中断)(可能是毫秒)
有人知道我如何解决这个问题,或者以其他方式更新标签吗?
答案 0 :(得分:0)
您的代码中有一些错误。
durationSlider
的值。 JavaFX是单线程的,只能从 JavaFX Application Thread 访问GUI。
Platform.runLater
(但还有一个更好的选择,请参阅第4点)。setCurrentTime
字段不是volatile
,但是您正在后台线程上对其进行写入,并在 JavaFX Application Thread 中对其进行读取。这意味着一个线程的更新不能保证被另一个线程看到。
isPlaying
可能也是个问题,但您没有显示其声明。updateValues()
时,您都会启动一个新线程!
MediaPlayer.currentTime
属性通常会失效,您最终将拥有很多线程。currentTime.format(...)
。 String.format
方法是静态的,最好这样调用它:String.format(...)
。
format
是一个实例方法。关于第4点:
无需使用后台线程来更新durationSlider
或displayCurrentTime
。 currentTime
的{{1}}属性将在媒体播放时自动更新(并每次通知所有侦听器)。这些更新将在 JavaFX Application Thread 上进行。您需要做的就是更新侦听器中的UI。由于计算并不昂贵,因此可以在 JavaFX Application Thread 上进行计算。
MediaPlayer
以上代码使用mp.currentTimeProperty().addListener((observable, oldTime, newTime) -> {
durationSlider.setValue(newTime.toMillis() / mp.getTotalDuration().toMillis() * 100);
String formattedTime = ...; // your computations
displayCurrentTime.setText(formattedTime);
});
而不是javafx.beans.value.ChangeListener
。它也使用lambda。但是,如果您不想使用lambda(或不知道它们),则该代码等效于:
InvalidationListener