【发布时间】:2011-10-01 01:43:44
【问题描述】:
我有一个 N 个 JSlider 的列表(N 在程序上不会改变,只是在我添加更多功能时。目前 N 等于 4)。所有滑块值的总和必须等于 100。当一个滑块移动时,其余滑块应进行调整。每个滑块的值范围从 0 到 100。
目前我在更改滑块时使用此逻辑(伪代码):
newValue = currentSlider.getValue
otherSliders = allSliders sans currentSlider
othersValue = summation of otherSliders values
properOthersValue = 100 - newValue
ratio = properOthersValue / othersValue
for slider in otherSlider
slider.value = slider.getValue * ratio
此设置的问题是滑块的值存储为整数。因此,当我调整滑块时,我会遇到精度问题:滑块会根据比率值抽动或根本不移动。此外,总值并不总是等于 100。
在不创建支持浮点数或双精度数的全新 JSlider 类的情况下,有没有人可以解决这个问题?
如果您想了解我想要的行为示例,请访问:Humble Indie Bundle 并滚动到页面底部。
谢谢
附言将值乘以比率允许用户将值“锁定”为 0。但是,当 4 个滑块中的 3 个为 0 且第 4 个滑块为 100 并且我将第 4 个滑块向下移动时,我不确定该怎么做.使用上面的逻辑,以 0 为值的 3 个滑块保持不变,第 4 个滑块移动到用户放置的位置,这使得总数小于 100,这是不正确的行为。
编辑
这里是 SSCCE:
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.util.LinkedList;
public class SliderDemo
{
static LinkedList<JSlider> sliders = new LinkedList<JSlider>();
static class SliderListener implements ChangeListener
{
boolean updating = false;
public void stateChanged(ChangeEvent e)
{
if (updating) return;
updating = true;
JSlider source = (JSlider)e.getSource();
int newValue = source.getValue();
LinkedList<JSlider> otherSliders = new LinkedList<JSlider>(sliders);
otherSliders.remove(source);
int otherValue = 0;
for (JSlider slider : otherSliders)
{
otherValue += slider.getValue();
}
int properValue = 100 - newValue;
double ratio = properValue / (double)otherValue;
for (JSlider slider : otherSliders)
{
int currentValue = slider.getValue();
int updatedValue = (int) (currentValue * ratio);
slider.setValue(updatedValue);
}
int total = 0;
for (JSlider slider : sliders)
{
total += slider.getValue();
}
System.out.println("Total = " + total);
updating = false;
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("SliderDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = frame.getContentPane();
JPanel sliderPanel = new JPanel(new GridBagLayout());
container.add(sliderPanel);
SliderListener listener = new SliderListener();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
int sliderCount = 4;
int initial = 100 / sliderCount;
for (int i = 0; i < sliderCount; i++)
{
gbc.gridy = i;
JSlider slider = new JSlider(0, 100, initial);
slider.addChangeListener(listener);
slider.setMajorTickSpacing(50);
slider.setPaintTicks(true);
sliders.add(slider);
sliderPanel.add(slider, gbc);
}
frame.pack();
frame.setVisible(true);
}
}
【问题讨论】:
-
最好的办法是创建一个SSCCE 并在此处发布代码。请在回复之前阅读链接,因为我们绝对不想看到您的整个程序。
-
请参阅下面我的回答中的示例代码。
-
在 Swing 中,答案始终是自定义模型。尽管 Slider 并没有得到应有的尊重:stackoverflow.com/questions/7468314/…
-
玩过这个之后我不会推荐这种UI。使用和获得您想要的值非常困难。例如,尝试我的解决方案并将值从“20、20、20、20、20”更改为“40、30、20、10、0”。您需要操作各种滑块多少次? (我最好的是10)。我认为更好的解决方案是让这些值仅影响您当前正在更改的滑块下方的滑块。这样,您可以保证在操作最多 4 个滑块后得到解决方案。
-
@kleopatra 这是个好建议,但我不知道我是否可以让它与模型一起使用