Reputation: 31
Is it possible to stop a jslider from moving or changing values when it is clicked on? I want my jslider only to move when it is dragged. I don't want it to do anything at all when I click on it. Would someone please help me with this one.
Upvotes: 3
Views: 1109
Reputation: 9808
There are a few other examples:
slider1
: Override TrackListener#shouldScroll(...)
method to always return false
.slider2
: Change the left mouse button pressed MouseEvent
as a right button by using JLayer
.import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.MetalSliderUI;
public class MainPanel {
public JComponent makeUI() {
JSlider slider0 = new JSlider();
JSlider slider1 = new JSlider() {
@Override public void updateUI() {
super.updateUI();
setUI(new MetalSliderUI() {
@Override protected TrackListener createTrackListener(JSlider slider) {
return new TrackListener() {
@Override public boolean shouldScroll(int direction) {
return false;
}
};
}
});
}
};
//http://stackoverflow.com/questions/9736237/how-to-disable-position-change-of-jslider-on-mouse-right-click
UIManager.put("Slider.onlyLeftMouseButtonDrag", false);
JSlider slider2 = new JSlider();
Box box = Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 20));
box.add(makeTitledPanel("Default", slider0));
box.add(Box.createVerticalStrut(20));
box.add(makeTitledPanel(
"Override TrackListener#shouldScroll(...): false", slider1));
box.add(Box.createVerticalStrut(20));
box.add(makeTitledPanel(
"JLayer + Slider.onlyLeftMouseButtonDrag: false",
new JLayer<JSlider>(slider2, new DisableLeftPressedLayerUI())));
box.add(Box.createVerticalGlue());
return box;
}
private static JComponent makeTitledPanel(String title, JComponent c) {
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createTitledBorder(title));
p.add(c, BorderLayout.NORTH);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new MainPanel().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class DisableLeftPressedLayerUI extends LayerUI<JSlider> {
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(MouseEvent e, JLayer<? extends JSlider> l) {
if (e.getID() == MouseEvent.MOUSE_PRESSED && SwingUtilities.isLeftMouseButton(e)) {
JSlider slider = (JSlider) e.getComponent();
MouseEvent me = new MouseEvent(
slider,
e.getID(), e.getWhen(),
InputEvent.BUTTON3_DOWN_MASK, //e.getModifiers(),
e.getX(), e.getY(),
e.getXOnScreen(), e.getYOnScreen(),
e.getClickCount(),
e.isPopupTrigger(),
MouseEvent.BUTTON3); //e.getButton());
e.consume();
slider.dispatchEvent(me);
}
}
}
Upvotes: 1
Reputation:
Unfortunately, after a fair amount of testing, I could not find any method nor combination of event listeners that could solve this problem. The closest I got was disabling all modifications to slider value, no matter how it was changed:
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class App {
public static void main(String[] args) {
final JFrame jframe = new JFrame("Demo");
final JSlider jslider = new JSlider();
// Limit user access
new SliderLocker(jslider).preventSlide = true;
jslider.setMajorTickSpacing(10);
jslider.setPaintTicks(true);
jframe.getContentPane().add(jslider);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(400, 400);
jframe.setResizable(false);
jframe.setVisible(true);
}
// Create custom event handler to restore to original value with event system
private static class SliderLocker implements ChangeListener {
public boolean preventSlide = false;
private int oldVal;
private final JSlider comp;
public SliderLocker(JSlider c){
comp = c;
oldVal = c.getValue();
c.addChangeListener(this);
}
@Override
public void stateChanged(ChangeEvent ev){
if(preventSlide){
comp.setValue(oldVal);
}
}
}
}
Basically it creates a new SliderLocker
which has a public flag .preventSlide
. When set to true
, it will prevent all user interactions (and even code-triggred interactions, such as .setValue()
).
My previous code had included some mouse listeners that would attempt to check if the slider was being 'slid' (changed with actual mouse drag) but I later found out that holding down mouse out of slider button and dragging broke the handler.
Upvotes: 0