Java:强制 JSlider 在拖动时从鼠标 detached/released

Java: force JSlider to be detached/released from mouse when dragged

我正在使用 JSlider 在自定义 Java 音乐播放器应用程序中搜索音频文件。当滑块被释放时,播放器跳转到相应的媒体时间。我想要实现的是以下内容:当拖动滑块时按下 ESCAPE 时,我希望它从鼠标光标 released/detached 并跳转回到原来的位置。换句话说:我想interrupt/stop用户手动拖动。

我尝试了以下方法来实现这一点:

  1. 呼叫slider.setValue(initialValue)
  2. 触发自定义 mouseReleased() 事件(即使鼠标仍在按下)
  3. 触发自定义 windowDeactivated() 事件 主框架撤回滑块它的焦点

没有任何效果。滑块的旋钮一直粘在鼠标上,直到我松开它。还有其他方法可以实现吗?

import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;

public class DetachSlider {

    // true when slider is being dragged
    private boolean dragged;
    
    public static void main (String[] args) {
        new DetachSlider().initFrame();
    }
    
    public void initFrame() {

        JFrame frame = new JFrame();
        frame.setTitle("Detach Slider Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                
        JSlider slider = new JSlider();
        slider.setPreferredSize(new Dimension(500,50));
        slider.addMouseListener(new MouseHandler());
        slider.addKeyListener(new KeyHandler());
        
        JPanel panel = new JPanel();
        panel.setBorder(new CompoundBorder(new EmptyBorder(5,5,5,5), new BevelBorder(BevelBorder.LOWERED)));
        panel.add(slider);

        frame.setContentPane(panel);
        frame.setLocation(500,400);
        frame.pack();
        frame.setVisible(true);
    }

    // MouseListener for Slider
    private class MouseHandler extends MouseAdapter {
        public void mousePressed(MouseEvent me) {
            dragged = true;
        }
        public void mouseReleased(MouseEvent me) {
            dragged = false;
        }
    }
    
    // KeyListener for Slider
    private class KeyHandler extends KeyAdapter {
        public void keyPressed (KeyEvent ke) {
            if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
                JSlider slider = (JSlider)ke.getSource();
                if (dragged) {
                    System.out.println("ESCAPE pressed when slider is dragged");
                    slider.setValue(0);
                }
                else {
                    System.out.println("ESCAPE pressed when slider is idle");
                    slider.setValue(0);
                }
            }
        }
    }

}

好的,我想我们有一个解决方案。就是将mouseRelease事件发送给所有附着在slider上的mouseListener。如下:

MouseListener[] cs=slider.getMouseListeners();
MouseEvent me = new MouseEvent((JSlider)ke.getSource(), MouseEvent.MOUSE_RELEASED, 0, 0, 100, 100, 1, false);
for(MouseListener m:cs) m.mouseReleased(me);

这发生在 keyPressed 方法内部。