我有一个具有65536个不同值的JSlider。它适用于粗调和非常精细的调整(使用向上/向下箭头+/- 1),但在中间非常差。
那里有什么会更好吗?我可以模糊地设想用2个滑块来进行粗略+微调,但是无法弄清楚如何让它们一起工作。
答案 0 :(得分:1)
使用JSpinner
代替JSlider
怎么样?使用SpinnerNumberModel
,您可以设置步长,甚至可以动态更改步长。
如果您可以使用多个控件,您甚至可以使用两个微调器,一个用于设置值,另一个用于设置第一个微调器使用的步长。
有关此示例,我从SliderDemo获取了Swing slider tutorial代码,并将其修改为使用两个JSpinners
而不是一个JSlider
。这是我改变的代码中最有趣的部分:
//Create the slider^H^H^H^H^H^H spinners.
// JSlider framesPerSecond = new JSlider(JSlider.HORIZONTAL,
// FPS_MIN, FPS_MAX, FPS_INIT);
final int initStep = 1;
final SpinnerNumberModel animationModel = new SpinnerNumberModel(FPS_INIT,
FPS_MIN,
FPS_MAX,
initStep);
final SpinnerNumberModel stepSizeModel = new SpinnerNumberModel(initStep,
1,
10,
1);
final JSpinner framesSpinner = new JSpinner(animationModel);
framesSpinner.addChangeListener(this);
final JSpinner stepSpinner = new JSpinner(stepSizeModel);
stepSpinner.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent arg0)
{
animationModel.setStepSize(stepSizeModel.getNumber());
}
});
我还必须进行一些不太有趣的更改,例如为步长微调器创建标签,将新标签和新微调器添加到容器,以及更改{{1}上的stateChanged()
方法将事件源转换为this
而不是将其转换为JSpinner
。
当然,您可以进一步详细说明这一点,例如增加步长微调器的步长(例如,这样您只需单击一下就可以将步长从1更改为101)。您还可以使用其他控件而不是JSlider
来设置步长,例如组合框。
最后,为了使这一切都很容易使用,你可能想要连接一些击键加速器(可能通过一个菜单?),这样你就可以改变步长,而无需实际移动鼠标或键盘焦点旋转到另一个。
编辑:鉴于您无论如何必须使用JSpinner
,您是否知道可以使用PgUp / PgDn上下移动1/10 总的范围??
如果要更改1/10 th 数量(例如使其动态化),则需要覆盖方法JSlider
。
这是一个例子,我只是将BasicSliderUI.scrollByBlock()
的UI类覆盖到该范围的1/4 th ,而不是1/10 th :
JSlider
从这里开始,用另一个滑块或微调器设置的变量替换那个常量//Create the slider.
JSlider framesPerSecond = new JSlider(JSlider.HORIZONTAL,
FPS_MIN, FPS_MAX, FPS_INIT);
framesPerSecond.setUI(new javax.swing.plaf.metal.MetalSliderUI() {
private static final int SLIDER_FRACTION = 4;
/**
* This code is cut, paste, and modified from
* {@link javax.swing.plaf.basic.BasicSliderUI#scrollByBlock(int).
* I should be ashamed of cutting and pasting, but whoever hardcoded the magic
* number "10" in the original code should be more ashamed than me. ;-)
*
* @param direction
* either +1 or -1
*/
@Override
public void scrollByBlock(final int direction) {
synchronized(slider) {
int oldValue = slider.getValue();
int blockIncrement = (slider.getMaximum() - slider.getMinimum()) / SLIDER_FRACTION;
if (blockIncrement <= 0 && slider.getMaximum() > slider.getMinimum()) {
blockIncrement = 1;
}
int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
slider.setValue(oldValue + delta);
}
}
});
并不会太难,是吗?