【发布时间】:2010-10-05 19:56:50
【问题描述】:
每当我单击一个 JSlider 时,它都会在单击方向上定位一个 majorTick,而不是跳转到我实际单击的位置。 (如果滑块位于点 47 并且我单击 5,它将跳转到 37 而不是 5)。使用 JSlider 时有什么方法可以改变这一点,还是我必须使用其他数据结构?
【问题讨论】:
标签: java swing user-interface jslider
每当我单击一个 JSlider 时,它都会在单击方向上定位一个 majorTick,而不是跳转到我实际单击的位置。 (如果滑块位于点 47 并且我单击 5,它将跳转到 37 而不是 5)。使用 JSlider 时有什么方法可以改变这一点,还是我必须使用其他数据结构?
【问题讨论】:
标签: java swing user-interface jslider
虽然这看起来很奇怪,但实际上是外观控制了这种行为。看一下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);
}
});
【讨论】:
这个问题有点老了,但我自己也遇到过这个问题。这是我的解决方案:
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);
}
};
【讨论】:
此行为源自操作系统。您确定要重新定义它并迷惑用户吗?我不这么认为。 ;)
【讨论】: