gpt4 book ai didi

Java JSlider精度问题

转载 作者:搜寻专家 更新时间:2023-11-01 01:28:58 25 4
gpt4 key购买 nike

我有一个包含 N 个 JSlider 的列表(N 在程序上不会改变,只会在我添加更多功能时改变。目前 N 等于 4)。所有 slider 值的总和必须等于 100。当一个 slider 移动时,其余 slider 应进行调整。每个 slider 的值都在 0 到 100 之间。

目前我在更改 slider 时使用此逻辑(伪代码):

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

此设置的问题是 slider 的值存储为整数。因此,当我调整 slider 时,我遇到了精度问题: slider 会根据比率值抽动或根本不动。此外,总值并不总是加起来为 100。

有没有人能在不创建支持 float 或 double 的全新 JSlider 类的情况下解决这个问题?

如果您想要我想要的行为示例,请访问:Humble Indie Bundle并滚动到页面底部。

谢谢

附注将值乘以比率允许用户将值“锁定”为 0。但是,当 4 个 slider 中的 3 个为 0 而第 4 个 slider 为 100 并且我将第 4 个 slider 向下移动时,我不确定该怎么做.使用上面的逻辑,值为 0 的 3 个 slider 保持不变,第 4 个 slider 移动到用户放置它的位置,这使得总数小于 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);
}
}

最佳答案

为什么不通过让 JSlider 模型的粒度从 0 到 1000000 并且总和为 1000000 来使 JSlider 模型的粒度更细?使用适合 LabelTable 的 Dictionary,用户可能不知道它不是从 0 到 100。

例如:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

@SuppressWarnings("serial")
public class LinkedSliders2 extends JPanel {
private static final int SLIDER_COUNT = 5;
public static final int SLIDER_MAX_VALUE = 1000;
private static final int MAJOR_TICK_DIVISIONS = 5;
private static final int MINOR_TICK_DIVISIONS = 20;
private static final int LS_WIDTH = 700;
private static final int LS_HEIGHT = 500;
private JSlider[] sliders = new JSlider[SLIDER_COUNT];
private SliderGroup2 sliderGroup = new SliderGroup2(SLIDER_MAX_VALUE);

public LinkedSliders2() {
Dictionary<Integer, JComponent> myDictionary = new Hashtable<Integer, JComponent>();
for (int i = 0; i <= MAJOR_TICK_DIVISIONS; i++) {
Integer key = i * SLIDER_MAX_VALUE / MAJOR_TICK_DIVISIONS;
JLabel value = new JLabel(String.valueOf(i * 100 / MAJOR_TICK_DIVISIONS));
myDictionary.put(key, value);
}
setLayout(new GridLayout(0, 1));
for (int i = 0; i < sliders.length; i++) {
sliders[i] = new JSlider(0, SLIDER_MAX_VALUE, SLIDER_MAX_VALUE
/ SLIDER_COUNT);
sliders[i].setLabelTable(myDictionary );
sliders[i].setMajorTickSpacing(SLIDER_MAX_VALUE / MAJOR_TICK_DIVISIONS);
sliders[i].setMinorTickSpacing(SLIDER_MAX_VALUE / MINOR_TICK_DIVISIONS);
sliders[i].setPaintLabels(true);
sliders[i].setPaintTicks(true);
sliders[i].setPaintTrack(true);
sliderGroup.addSlider(sliders[i]);
add(sliders[i]);
}
}

@Override
public Dimension getPreferredSize() {
return new Dimension(LS_WIDTH, LS_HEIGHT);
}

private static void createAndShowGui() {
LinkedSliders2 mainPanel = new LinkedSliders2();

JFrame frame = new JFrame("LinkedSliders");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

class SliderGroup2 {
private List<BoundedRangeModel> sliderModelList = new ArrayList<BoundedRangeModel>();
private ChangeListener changeListener = new SliderModelListener();
private int maxValueSum;

public SliderGroup2(int maxValueSum) {
this.maxValueSum = maxValueSum;
}

public void addSlider(JSlider slider) {
BoundedRangeModel model = slider.getModel();
sliderModelList.add(model);
model.addChangeListener(changeListener);
}

private class SliderModelListener implements ChangeListener {
private boolean internalChange = false;

@Override
public void stateChanged(ChangeEvent cEvt) {
if (!internalChange) {
internalChange = true;
BoundedRangeModel sourceModel = (BoundedRangeModel) cEvt.getSource();
int sourceValue = sourceModel.getValue();

int oldSumOfOtherSliders = 0;
for (BoundedRangeModel model : sliderModelList) {
if (model != sourceModel) {
oldSumOfOtherSliders += model.getValue();
}
}
if (oldSumOfOtherSliders == 0) {
for (BoundedRangeModel model : sliderModelList) {
if (model != sourceModel) {
model.setValue(1);
}
}
internalChange = false;
return;
}

int newSumOfOtherSliders = maxValueSum - sourceValue;

for (BoundedRangeModel model : sliderModelList) {
if (model != sourceModel) {
long newValue = ((long) newSumOfOtherSliders * model
.getValue()) / oldSumOfOtherSliders;
model.setValue((int) newValue);
}
}

int total = 0;
for (BoundedRangeModel model : sliderModelList) {
total += model.getValue();
}
//!! System.out.printf("Total = %.0f%n", (double)total * 100 / LinkedSliders2.SLIDER_MAX_VALUE);

internalChange = false;
}
}

}

}

编辑为让 SliderGroup2 使用 BoundedRangeModels 列表而不是 JSliders。

关于Java JSlider精度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7617605/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com