简体   繁体   English

单击时停止移动jslider

[英]Stopping the jslider from moving when clicked

Is it possible to stop a jslider from moving or changing values when it is clicked on? 是否可以在单击时阻止jslider移动或更改值? I want my jslider only to move when it is dragged. 我希望我的jslider只在拖动时移动。 I don't want it to do anything at all when I click on it. 当我点击它时,我不希望它做任何事情。 Would someone please help me with this one. 有人请帮助我这个。

There are a few other examples: 还有一些其他例子:

  • slider1 : Override TrackListener#shouldScroll(...) method to always return false . slider1 :覆盖TrackListener#shouldScroll(...)方法以始终返回false
  • slider2 : Change the left mouse button pressed MouseEvent as a right button by using JLayer . slider2 :使用JLayer更改鼠标左键,将MouseEvent作为右键。
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);
    }
  }
}

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 . 基本上它创建了一个新的SliderLocker ,它有一个公共标志.preventSlide When set to true , it will prevent all user interactions (and even code-triggred interactions, such as .setValue() ). 设置为true ,它将阻止所有用户交互(甚至是代码触发的交互,例如.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. 我之前的代码包含了一些鼠标监听器,它们试图检查滑块是否“滑动”(用实际的鼠标拖动改变)但我后来发现按住鼠标滑出按钮并拖动打破了处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM