swing:JSlider但有粗/细控制?

时间:2009-12-29 19:59:07

标签: swing jslider

我有一个具有65536个不同值的JSlider。它适用于粗调和非常精细的调整(使用向上/向下箭头+/- 1),但在中间非常差。

那里有什么会更好吗?我可以模糊地设想用2个滑块来进行粗略+微调,但是无法弄清楚如何让它们一起工作。

1 个答案:

答案 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); } } }); 并不会太难,是吗?