swing:JSlider,但具有粗略/精细控制?

swing:JSlider,但具有粗略/精细控制?,swing,jslider,Swing,Jslider,我有一个JSlider,有65536个不同的值。它对于粗调整和非常精细的调整(+/- 1使用上/下箭头)非常有效,但是在中间是非常差的。 有没有更好的办法?我可以模糊地想象用两个滑块一个进行粗略+精细的调整,但我真的不知道如何让它们一起工作。用JSpinner代替JSlider怎么样?使用SpinnerNumberModel,您可以设置步长,甚至可以动态更改步长 如果可以使用多个控件,甚至可以使用两个微调器,一个用于设置值,另一个用于设置第一个微调器使用的步长 例如,我从中获取代码,并将其修改为

我有一个JSlider,有65536个不同的值。它对于粗调整和非常精细的调整(+/- 1使用上/下箭头)非常有效,但是在中间是非常差的。
有没有更好的办法?我可以模糊地想象用两个滑块一个进行粗略+精细的调整,但我真的不知道如何让它们一起工作。

JSpinner
代替
JSlider
怎么样?使用
SpinnerNumberModel
,您可以设置步长,甚至可以动态更改步长

如果可以使用多个控件,甚至可以使用两个微调器,一个用于设置值,另一个用于设置第一个微调器使用的步长

例如,我从中获取代码,并将其修改为使用两个
jspinner
,而不是一个
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());
    } 
});
我还必须做一些不太有趣的更改,例如为步长微调器创建标签,将新标签和新微调器添加到容器中,以及更改
stateChanged()
上的
方法将事件源强制转换为
JSpinner
而不是强制转换为
JSlider

当然,您可以对此进行进一步阐述,例如增加“步长”微调器的步长(例如,您可以通过单击将步长从1更改为101)。您还可以使用不同的控件而不是
JSpinner
来设置步长,例如组合框

最后,为了使这一切真正易于使用,您可能希望连接一些击键加速器(可能通过菜单?),这样您就可以更改步长,而无需将鼠标或键盘焦点从一个微调器移动到另一个微调器

编辑:考虑到无论如何都必须使用
JSlider
,您是否知道可以使用PgUp/PgDn上下移动总范围的1/10

如果要更改十分之一的金额(例如使其成为动态的),则需要重写方法
BasicSliderUI.scrollByBlock()

下面是一个示例,我刚刚将
JSlider
的UI类改写为1/4的步长,而不是1/10:

//创建滑块。
JSlider framesPerSecond=新的JSlider(JSlider.HORIZONTAL,
FPS_最小值、FPS_最大值、FPS_初始值);
framesPerSecond.setUI(新的javax.swing.plaf.metal.MetalSliderUI(){
私有静态最终整数滑块_分数=4;
/**
*此代码是从中剪切、粘贴和修改的
*{@linkjavax.swing.plaf.basic.BasicSliderUI#scrollByBlock(int)。
*我应该为剪切和粘贴感到羞耻,但是谁硬编码了魔法
*原始代码中的数字“10”应该比我更羞愧。;-)
*
*@param方向
*+1或-1
*/   
@凌驾
公共无效滚动块(最终整数方向){
同步(滑块){
int oldValue=slider.getValue();
int blockIncrement=(slider.getMaximum()-slider.getMinimum())/slider\u分数;
if(blockIncrement slider.getMinimum()){
块增量=1;
}
int delta=块增量*((方向>0)?正滚动:负滚动);
slider.setValue(旧值+增量);
}
}
});

从这里开始,用一个由另一个滑块或微调器设置的变量替换常量
SLIDER\u FRACTION
,不是很难吗?

谢谢,我也喜欢微调器,但我需要在这个应用程序中使用一个滑块。也许微调器+滑块组合会很好。如果你一定要使用滑块,那么也许你可以通过动态修改勾号间距并启用“捕捉到勾号”行为来获得所需的行为?我不确定这与使用滑块上的箭头键如何交互,但值得研究。好的,我找到了一种方法,只需使用
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);          
        }
    }
});