有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在JavaFx音乐播放器中获得歌曲持续时间

我已经用JavaFX创建了一个音乐播放器。然而,我无法理解如何知道我当前播放的歌曲的持续时间

编辑:我在代码中添加了以下行,现在歌曲的持续时间可见。但是,当我播放下一首歌曲时,歌曲的持续时间不可见。 下面是我添加到代码中的行:

mediaPlayer.currentTimeProperty().addListener(new TimeListener());  

TimeListener = new ChangeListener<Duration>() 
        {
              @Override public void changed(ObservableValue<? extends Duration> o, Duration oldVal, Duration newVal) 
              {
             //now newVal is of Duration class
              }
            };

    }
    
    public class TimeListener implements ChangeListener {
        public void changed(ObservableValue o, Object oldVal, Object newVal) {

        //Update time display with MediaPlayer's current time:
        playTime.setText(newVal.toString());
        }
    }

以下是我创建音乐播放器的代码:

    public class MusicController implements Initializable 
{
    @FXML
    private ImageView trackLogo;
    @FXML
    private Button next, previous, pause, play, reset;
    @FXML
    private Slider VolumeSlider;    
    @FXML
    private AnchorPane Panel;   
    @FXML
    private Label playTime, appTitle, songTitle;    
    @FXML
    private ProgressBar songProgressBar;
    @FXML
    private Media media;
    private MediaPlayer mediaPlayer;
    private File directory;
    private File [] files;
    private ArrayList<File> songs;  
    private int songNumber; 
    private Timer timer;
    private TimerTask task;
    private boolean running;
    private ChangeListener<Duration> TimeListener;
    
    @Override
    public void initialize(URL url, ResourceBundle rb) 
    {
        songs = new ArrayList<File>();      
        directory = new File("music");      
        files = directory.listFiles();      
        if(files!=null) 
        {
            for(File file : files)
            {
                songs.add(file);
                System.out.println(file);
            }
        }       
        media = new Media(songs.get(songNumber).toURI().toString());
        mediaPlayer = new MediaPlayer(media);
        mediaPlayer.currentTimeProperty().addListener(new TimeListener());      
        songTitle.setText(songs.get(songNumber).getName());
        VolumeSlider.valueProperty().addListener(new ChangeListener<Number>()
                {
                    public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) 
                    {       
                        mediaPlayer.setVolume(VolumeSlider.getValue() * 0.01);  
                    }
                });
        
        TimeListener = new ChangeListener<Duration>() 
        {
              @Override public void changed(ObservableValue<? extends Duration> o, Duration oldVal, Duration newVal) 
              {
             //now newVal is of Duration class
              }
            };

    }
    
    public class TimeListener implements ChangeListener {
        public void changed(ObservableValue o, Object oldVal, Object newVal) {

        //Update time display with MediaPlayer's current time:
        playTime.setText(newVal.toString());
        }
    }
    
    public void playMedia() 
    {   
            beginTimer();
            mediaPlayer.setVolume(VolumeSlider.getValue() * 0.01);
            mediaPlayer.play();
    }
    
    public void pauseMedia() 
    {   
            cancelTimer();
            mediaPlayer.pause();
    }

    public void resetMedia() 
    {   
            songProgressBar.setProgress(0);
            mediaPlayer.seek(Duration.seconds(0));
    }
    
    public void previousMedia() 
    {   
        if (songNumber > 0)
        {
            songNumber--;
            mediaPlayer.stop();
            
            if(running)
            {
                cancelTimer();
            }
            
            media = new Media(songs.get(songNumber).toURI().toString());
            mediaPlayer = new MediaPlayer(media);
            songTitle.setText(songs.get(songNumber).getName());
            playMedia();

        }
        else
        {
            songNumber = songs.size() - 1;
            mediaPlayer.stop();
            
            if(running)
            {
                cancelTimer();
            }
            
            
            media = new Media(songs.get(songNumber).toURI().toString());
            mediaPlayer = new MediaPlayer(media);
            songTitle.setText(songs.get(songNumber).getName());
            playMedia();
        }
    }
    
    public void nextMedia() 
    {   
        if (songNumber < songs.size() - 1)
        {
            songNumber++;
            mediaPlayer.stop();
            
            if(running)
            {
                cancelTimer();
            }
    
            media = new Media(songs.get(songNumber).toURI().toString());
            mediaPlayer = new MediaPlayer(media);
            songTitle.setText(songs.get(songNumber).getName());
            playMedia();

        }
        else
        {
            songNumber = 0;
            mediaPlayer.stop();
            
            if(running)
            {
                cancelTimer();
            }
            media = new Media(songs.get(songNumber).toURI().toString());
            mediaPlayer = new MediaPlayer(media);
            songTitle.setText(songs.get(songNumber).getName());
            playMedia();
        }
    }
    
    
    public void beginTimer() 
    {   
        timer = new Timer();
        task = new TimerTask()
                {   
                    public void run() 
                    {
                        running = true;
                        double current = mediaPlayer.getCurrentTime().toSeconds();
                        double end = media.getDuration().toSeconds();
                        System.out.println(current/end);
                        songProgressBar.setProgress(current/end);
                        
                        if (current/end ==1)
                        {
                            cancelTimer();
                        }
                        
                    }
                };
                timer.scheduleAtFixedRate(task, 0, 1000);
    }
    
    public void cancelTimer() 
    {   
            running = false;
            timer.cancel();
    }
    
}

我试着阅读Oracle文档(https://docs.oracle.com/javase/8/javafx/media-tutorial/playercontrol.htm)和这个youtube视频(https://www.youtube.com/watch?v=-D2OIekCKes)来创建一个音乐播放器

如果有任何帮助,我将不胜感激。提前谢谢


共 (1) 个答案

  1. # 1 楼答案

    对于这种情况,不应该使用Timer或线程。MediaPlayer的属性是可观察的,因此您应该向它们添加侦听器,或者将UI属性绑定到它们。下面是一个将ProgressBar的进度属性绑定到播放器的示例:

    progressBar.progressProperty().bind(
        Bindings.createDoubleBinding(() -> {
          Duration current = mediaPlayer.getCurrentTime();
          Duration total = mediaPlayer.getCycleDuration();
          return current.toMilli() / total.toMillis();
        },
        mediaPlayer.currentTimeProperty(),
        mediaPlayer.cycleDurationProperty())
    );
    

    上面使用了Bindings#createDoubleBinding(Callable,Observable...)lambda expressions

    每次创建一个新的MediaPlayer时,您都需要执行上述操作,否则就可以使进度条保持最新。你可以对标签做类似的事情,比如,以人类可读的格式显示当前时间和总时间

    此外,您可以执行以下操作,而不是将侦听器添加到volumeSlider

    mediaPlayer.volumeProperty().bind(volumeSlider.valueProperty());
    

    有关更多信息,请参见Using JavaFX Properties and Binding


    顺便说一句,你不仅不应该在这里使用Timer,而且你使用它的方式是不正确的。在JavaFX中,有一个特殊的线程名为JavaFX应用程序线程。只有该线程应该直接或间接地与UI交互。使用任何其他线程与UI交互都是错误的代码,可能会导致未定义的行为JavaFX不是线程安全的

    可以使用Platform#runLater(Runnable)在FX线程上调度操作