Make a seek bar for media player.

若如初见. 提交于 2019-12-04 13:39:35

The problem with using a slider for this is that when the slider position is moved programmatically, it fires events. When an event is fired on a slider, it typically means the app. has to do something, such as move the song position. The effect is a never ending loop. There is probably a way around this by setting flags and ignoring some events, but I decided to go a different way.

Instead I used a JProgressBar to indicate the location in the track, and a MouseListener to detect when the user clicks on a separate position. Update the progress bar use a Swing Timer that checks the track location every 50-200 milliseconds. When a MouseEvent is detected, reposition the track.

The bar can be seen in the upper right of this GUI. Hovering over it will produce a tool tip showing the time in the track at that mouse position.

You could use a JSlider.

You can learn more from the Slider tutorial

You don't have to revalidate the container in order to change the slider.

Use these lines each time a new player is created:

  slider.setMinimum(0);
  slider.setMaximum(duration);
  slider.setValue(0);

  new UpdateWorker(duration).execute();

where duration is the variable holding the duration of the song in seconds.

And here is the code (used as inner class) which updates the slider:

private class UpdateWorker extends SwingWorker<Void, Integer> {

    private int duration;

    public UpdateWorker(int duration) {
        this.duration = duration;
    }

    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 1; i <= duration; i++) {
            Thread.sleep(1000);
            publish(i);
        }
        return null;
    }

    @Override
    protected void process(List<Integer> chunks) {
        slider.setValue(chunks.get(0));
    }

}

Now the slider will move to the right until the end of the song.

Also note that unless you want to use a custom slider, JMF provides a simple (and working) slider via player.getVisualComponent() (see this example).

UPDATE

In order to pause/resume the worker thread (and thus the slider and the song), here is an example with a button that sets the appropriate flags.

private boolean isPaused = false;
JButton pause = new JButton("Pause");
pause.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        JButton source = (JButton)e.getSource();
        if (!isPaused) {
            isPaused = true;
            source.setText("Resume");
        } else {
            isPaused = false;
            source.setText("Pause");
        }
    }
});

The method doInBackground should be changed to something like that:

@Override
protected Void doInBackground() throws Exception {
    for (int i = 0; i <= duration; i++) {
        if (!isPaused) {
            publish(i);
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
        while (isPaused) {
            try {
                Thread.sleep(50);
                continue;
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

Modify it accordingly to pause/resume the song along with the slider.

You should also consider @AndrewThompson's answer.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!