Java 不断变化的JSlider,用户交互事件?

Java 不断变化的JSlider,用户交互事件?,java,swing,jslider,Java,Swing,Jslider,我目前正在使用Java Swing开发一款小型MP3播放器。我想实现一个进度条,允许用户跳到一个随机位置。我认为使用JSlider可能是最好的选择 现在的问题是,我使用一个摆动计时器每200米更新一次进度条。这样,滑块的更改事件每次都会触发。是否有任何方法可以过滤掉不是由用户引起的事件调用 我目前正在尝试在计时器中使用setValueIsAdjusting(true),但这似乎非常不一致 Timer progressTimer = new Timer(200, e -> { upd

我目前正在使用Java Swing开发一款小型MP3播放器。我想实现一个进度条,允许用户跳到一个随机位置。我认为使用JSlider可能是最好的选择

现在的问题是,我使用一个摆动计时器每200米更新一次进度条。这样,滑块的更改事件每次都会触发。是否有任何方法可以过滤掉不是由用户引起的事件调用

我目前正在尝试在计时器中使用setValueIsAdjusting(true),但这似乎非常不一致

Timer progressTimer = new Timer(200, e -> {
    updateProgress(player.getPosition());
});
progressTimer.start();

progressSlider.addChangeListener(new ChangeListener() {
    @Override
    public void stateChanged(ChangeEvent e) {
        if (progressSlider.getValueIsAdjusting()) {
            return;
        }
        System.out.println("Skipping to "+progressSlider.getValue());
        player.skipTo(progressSlider.getValue());
    }
});

System.out有时打印用户单击的位置,有时打印滑块随计时器更新的位置。有什么帮助吗?

如果滑块没有调整,我只通过定时器更新滑块来解决问题:

Timer progressTimer = new Timer(200, e -> {
    if (!progressSlider.getValueIsAdjusting()) {
        updateProgress(player.getPosition());
    }
});
progressTimer.start();

progressSlider.addChangeListener(new ChangeListener() {
    @Override
    public void stateChanged(ChangeEvent e) {
        if (progressSlider.getValueIsAdjusting()) {
            return;
        }
        System.out.println("Skipping to "+progressSlider.getValue());
        player.skipTo(progressSlider.getValue());
    }
});

对于JSliders,我总是通过一个私有布尔标志来解决这个问题。在以编程方式设置JSlider值之前,我将标志设置为true。在JSlider事件代码的开头,如果标志为true,我将立即返回

将标志设置为false是一个棘手的部分,因为如果在以编程方式设置JSlider值之后立即这样做,那么更改事件甚至还没有执行,因此当它实际执行时,标志将为false,并且不会获得任何结果

摘自
SwingUtilities.invokeLater()的JavaDocs

“如果从事件调度线程调用invokeLater,[…]仍将被延迟,直到处理完所有挂起的事件。”

由于您已经在AWT EDT中,目标是让JSlider对更改做出反应(并立即返回),然后将标志设置为false,因此解决方案非常简单,从未让我失望过:

ignoreEvents = true;
jSlider.setValue(newValue);
SwingUtilities.invokeLater(() -> ignoreEvents = false);


编辑:

如果情况非常简单(您只想忽略一个事件),您可以这样做:

与上面一样,在调用setValue之前设置布尔标志。在JSlider事件代码中,如果设置了该标志,则清除该标志并返回。这里不需要SwingUtilities.invokeLater()




为什么不能在stateChanged事件中更新progressbar?嘿!您是否尝试过编写自己的模型类扩展并将其传递给JSpinner构造函数?你可以让模型从播放器本身获取信息,这样你就不再需要计时器了谢谢,塔巴基。我看了一眼,却没有明白你的确切意思。重写内部方法似乎对我没有帮助。我不再能够测试这一点,但它听起来很聪明,很有前途。不过,我会将其标记为解决方案,谢谢!谢谢,我第一次接受的解决方案:顺便说一句,我还没有在非Windows系统上测试过这个,但是我引用的文档显示了可靠的行为。