单击时停止移动jslider

时间:2016-10-06 19:24:51

标签: java swing slider jslider

是否可以在点击时阻止jslider移动或更改值?我希望我的jslider只在拖动时移动。当我点击它时,我不希望它做任何事情。 有人请帮助我这个。

2 个答案:

答案 0 :(得分:1)

还有一些其他例子:

  • slider1:覆盖TrackListener#shouldScroll(...)方法以始终返回false
  • slider2:使用MouseEvent将鼠标左键按下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);
    }
  }
}

答案 1 :(得分:0)

不幸的是,经过大量的测试后,我找不到任何可以解决这个问题的方法或事件监听器组合。我得到的最接近的是禁用对滑块值的所有修改,无论它如何更改:

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);
            }
        }
    }
}

基本上它会创建一个新的SliderLocker,其中包含公共标记.preventSlide。设置为true时,会阻止所有用户互动(甚至是代码触发的互动,例如.setValue())。

我之前的代码中包含了一些鼠标监听器,它们会尝试检查滑块是否正在滑动&#39; (用实际的鼠标拖动改变了)但后来我发现按住鼠标滑出按钮并拖动打破了处理程序。