У меня есть список из N JSliders (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 и прокрутите страницу до конца.
спасибо
p.s. Умножение значений на коэффициент позволяет пользователю «заблокировать» значения на 0. Однако я не уверен, что делать, когда 3 из 4 ползунков находятся на 0, а 4-й ползунок на 100, и я перемещаю 4-й ползунок вниз , Используя приведенную выше логику, 3 ползунка с 0 в качестве значения остаются на месте, а 4-й ползунок перемещается туда, куда его помещает пользователь, что в итоге составляет менее 100, что является неправильным поведением.
EDIT
Вот 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);
}
}