My JFrame window has system look and feel and when I add a JSlider and click on its line, it just goes 90 steps forward or backward depending on my mouse position. I want the diamond to go under my mouse and work as if I clicked and dragged on the diamond.
Here is a minimal program but I think this only happens in Windows because in default look and feel, it didnt snap to 90th numbers but only went ahead one number.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class Test extends JFrame {
int value = 300;
JSlider slider;
JLabel label;
public Test() {
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
label = new JLabel(String.valueOf(value));
slider = new JSlider();
slider.setMinimum(100);
slider.setMaximum(1000);
slider.setValue(value);
slider.setSnapToTicks(false);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
label.setText(String.valueOf(slider.getValue()));
}
});
add(label, BorderLayout.NORTH);
add(slider);
setVisible(true);
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Test();
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class SliderMousePressed extends JPanel
{
public SliderMousePressed()
{
JSlider slider = new JSlider(0, 50, 20);
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
add(slider);
snapToMouseClick( slider );
}
public static void snapToMouseClick(final JSlider slider)
{
MouseListener[] ml = slider.getMouseListeners();
for (MouseListener l : ml)
slider.removeMouseListener(l);
MouseMotionListener[] mml = slider.getMouseMotionListeners();
for (MouseMotionListener l : mml)
slider.removeMouseMotionListener(l);
final BasicSliderUI ui = (BasicSliderUI)slider.getUI();
BasicSliderUI.TrackListener tl = ui.new TrackListener()
{
// Position slider at mouse
@Override
public void mouseClicked(MouseEvent e)
{
Point p = e.getPoint();
int value = ui.valueForXPosition(p.x);
slider.setValue(value);
}
// Prevent scrolling while mouse button is held down
@Override
public boolean shouldScroll(int dir)
{
return false;
}
};
slider.addMouseListener(tl);
slider.addMouseMotionListener(tl);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("SliderMousePressed");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new SliderMousePressed() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
This example was based on this answer with a slight modification to remove/add the MouseMotionListener as well as the MouseListener to make the painting of the thumb slider more consistent with the default behaviour. Now the thumb will painted at the same relative position to the mouse instead of at the left, when the thumb is dragged.