I am using a JSlider
to seek through an audio file in a custom Java music player application. When the slider is released, the player jumps to the corresponding media time. What I want to achieve is the following: when ESCAPE
is pressed while the slider is being dragged, I want it to be released/detached from the mouse cursor and jump back to its initial position. In other words: I want to interrupt/stop the user's dragging manually.
I have tried the following to achieve this:
slider.setValue(initialValue)
mouseReleased()
event (even if the mouse was still being pressed)windowDeactivated()
event on
the main frame to withdraw the slider its focusNothing worked. The slider's knob keeps sticking to the mouse until I physically release it. Is there any other way I can achieve this?
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);
}
}
}
}
}
Ok I think we have a solution. It is to send the mouseRelease event to all the mouseListeners attached to the slider. As follows:
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);
This happens inside the keyPressed method.