【问题标题】:JSlider question: Position after leftclickJSlider问题:左键点击后的位置
【发布时间】:2010-10-05 19:56:50
【问题描述】:

每当我单击一个 JSlider 时,它都会在单击方向上定位一个 majorTick,而不是跳转到我实际单击的位置。 (如果滑块位于点 47 并且我单击 5,它将跳转到 37 而不是 5)。使用 JSlider 时有什么方法可以改变这一点,还是我必须使用其他数据结构?

【问题讨论】:

    标签: java swing user-interface jslider


    【解决方案1】:

    虽然这看起来很奇怪,但实际上是外观控制了这种行为。看一下BasicSliderUI,需要覆盖的方法是scrollDueToClickInTrack(int)

    为了将JSlider 的值设置为最接近用户在轨道上单击的位置的值,您需要在鼠标坐标从getMousePosition() 到有效的轨道值之间进行一些花哨的转换,考虑到Component 的位置,它的方向、大小和刻度之间的距离。幸运的是,BasicSliderUI 为我们提供了两个方便的函数:valueForXPosition(int xPos)valueForYPosition(int yPos)

    JSlider slider = new JSlider(JSlider.HORIZONTAL);
    slider.setUI(new MetalSliderUI() {
        protected void scrollDueToClickInTrack(int direction) {
            // this is the default behaviour, let's comment that out
            //scrollByBlock(direction);
    
            int value = slider.getValue(); 
    
            if (slider.getOrientation() == JSlider.HORIZONTAL) {
                value = this.valueForXPosition(slider.getMousePosition().x);
            } else if (slider.getOrientation() == JSlider.VERTICAL) {
                value = this.valueForYPosition(slider.getMousePosition().y);
            }
            slider.setValue(value);
        }
    });
    

    【讨论】:

    • 这有点奇怪,不错。试图弄清楚 scrollDue..(int) 的输入是如何创建的。为了确定方向,必须检查我单击比较滑块位置的位置。要确定这一点,是否不需要某些方法确切知道我单击滑块上的哪个位置?
    • 不是真的,方向很简单 - 对于水平轨道,它只需要知道鼠标点击的 x 坐标小于或大于滑块手柄的 x 坐标。
    • 是的,但要知道它是否小于或大于 X 坐标,您是否不需要知道单击滑块上的哪个位置进行比较?如果滑块手柄在 50 处,您需要知道单击位置以查看该位置是 > 还是
    • 只是为了澄清术语,“轨道”是标记刻度的水平/垂直条,“拇指”或“滑块”是您拖动的。我已经用我挖出的一些额外细节更新了上面的答案。希望这能让你更进一步。
    • 好的,现在看看上面的例子,它完全符合你的要求。
    【解决方案2】:

    这个问题有点老了,但我自己也遇到过这个问题。这是我的解决方案:

    JSlider slider = new JSlider(/* your options here if desired */) {
        {
            MouseListener[] listeners = getMouseListeners();
            for (MouseListener l : listeners)
                removeMouseListener(l); // remove UI-installed TrackListener
            final BasicSliderUI ui = (BasicSliderUI) getUI();
            BasicSliderUI.TrackListener tl = ui.new TrackListener() {
                // this is where we jump to absolute value of click
                @Override public void mouseClicked(MouseEvent e) {
                    Point p = e.getPoint();
                    int value = ui.valueForXPosition(p.x);
    
                    setValue(value);
                }
                // disable check that will invoke scrollDueToClickInTrack
                @Override public boolean shouldScroll(int dir) {
                    return false;
                }
            };
            addMouseListener(tl);
        }
    };
    

    【讨论】:

    • 这个解决方案不是意味着不能再使用滚轮来移动滑块了吗?
    • +1,我做了一点改动,也删除和​​添加了 MouseMotionListener。这带来了细微的外观变化,因为当您拖动拇指而不是跳到拇指的左边缘时,鼠标将保持在滑块拇指的中心。
    【解决方案3】:

    此行为源自操作系统。您确定要重新定义它并迷惑用户吗?我不这么认为。 ;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多