Question

I am using a JSlider in my application. I want only left click to slide JSlider, and I want to disable right click for JSlider. I am able to get event on right click, but slider is changing its value to other position.

jSlider.addChangeListener(new ChangeListener() {

    public void stateChanged(ChangeEvent e) {
        //code
    }
});

jSlider.addMouseListener(new MouseAdapter() {

    public void mouseReleased(MouseEvent e) {

        if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {
            //code
        } else {
            //code
        }

    }
});
Was it helpful?

Solution

I am using JDK1.7.0_03, Windows 7

UIManager.put("Slider.onlyLeftMouseButtonDrag", Boolean.TRUE);

JDK1.6.0_31:

Bug ID: 6614972 JSlider value should not change on right-click

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.metal.MetalSliderUI;

public class SliderOnlyLeftMouseButtonDragTest {
  public JComponent makeUI() {
    JSlider slider00 = new JSlider(0,10,5);
    JSlider slider01 = new JSlider(0,10,5);
    slider01.setUI(new MetalSliderUI() {
      protected TrackListener createTrackListener(JSlider slider) {
        return new TrackListener() {
          @Override public void mousePressed(MouseEvent e) {
            if(!SwingUtilities.isLeftMouseButton(e)) {
              return;
            }
            super.mousePressed(e);
          }
        };
      }
    });
    JPanel p = new JPanel();
    p.add(slider00);
    p.add(slider01);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new SliderOnlyLeftMouseButtonDragTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

OTHER TIPS

Another approach to work around bugs in ui listeners is to

  • find the listener
  • implement a wrapper which delegates to the original only if appropriate (here: not for right button)
  • remove the original and add the wrapper

The slight advantage compared with @aterai's approach is that it's independent of LAF, that is you can apply it in the exact same manner for each instead of subclassing the ui delegate for each.

In code something like:

MouseListener[] listeners = slider.getMouseListeners();
MouseListener uiListener = null;
for (MouseListener l : listeners) {
    LOG.info(l.getClass().getName());
    if (l.getClass().getName().contains("Track")) {
        uiListener = l; 
        break;
    }
}

final MouseListener delegate = uiListener;
MouseListener wrapper = new MouseListener() {

    @Override
    public void mouseClicked(MouseEvent e) {
        if (filter(e)) return;
        delegate.mouseClicked(e);
    }

    private boolean filter(MouseEvent e) {
        return SwingUtilities.isRightMouseButton(e);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (filter(e)) return;
        delegate.mousePressed(e);
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (filter(e)) return;
        delegate.mouseReleased(e);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        delegate.mouseEntered(e);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        delegate.mouseExited(e);
    }

};
slider.removeMouseListener(uiListener);
slider.addMouseListener(wrapper);

I Case he is not working with 1.7 First you must remove all mouseListeners from your slider

for (MouseListener ml : slider.getMouseListeners()){
    slider.removeMouseListener(ml);
}

after that you can implement your own mouseListener and add that one to the slider. In your mouselistener you must implement the calculations to set the value of your slider... e.g. sth like

public void mouseReleased(MouseEvent e) {

    if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {
        //code whatever should happen on right click
    } else {
        e.getX()*slider.getMaximum()/slider.getWidth();
    }

}

I guess the calculation could be improved because of rounding and so on.. But this idea should lead you to success

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top