多个JSlider激活和停用-共享值 [英] Multiple JSliders activating and deactivating - Sharing values

查看:116
本文介绍了多个JSlider激活和停用-共享值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文

我正在编写一段包含1个以上Sliders的代码.这些滑块组成一个组.该组滑块值的总和必须始终为100.但是,作为一项必需功能,用户可以禁用和启用(添加/删除)该组滑块.因此,这需要正确调整滑块值.

Im writing a piece of code that has 1+ Sliders. These sliders form a group. The sum of the slider values of this group must always be 100. However, as a NEEDED feature, the user can disable and enable (add/remove) sliders from this group. Therefore, this requires that the sliders values get adjusted properly.

尝试编写自己的小组代码后,我决定寻找一个更好的/经过测试和实施的代码.它比我的有所改善,但是出现了一些问题.

After attempting to code my own group, I decided to look for a better/tested and implemented code. It improved from mine, however, some issues appeared.

主要问题

通过选中或取消选中复选框来添加或删除滑块会导致错误,并且滑块会停止工作.请注意,在这种情况下,添加仅意味着启用先前禁用的滑块(通过取消选中复选框).

Adding or removing sliders by selection or deselection the checkbox causes errors and the sliders stop working. Notice that adding, in this scenario, just means enabling a previously disabled slider (by deselecting the checkbox).

初步解决方案

下面的代码在stackoverflow中找到.我确实在代码中实现了,但是由于无法发布,所以我决定调整在stackoverflow示例中找到的代码来表示我的情况.

The code below was found in stackoverflow. I did implement in my code but since I cant post it, I decided to adjust the code found in the stackoverflow example to represent my scenario.

如何?

任何帮助将不胜感激.我不确定如何解决此问题而不引起更多错误.我确实尝试过重新调整在更新方法上完成的演算,但这只会造成更多的废话.我在这里找不到所有尝试的成果,因为stackoverflow会说太多代码,而且我不确定它是否有助于找到答案.

Any help is greatly appreciated. Im not sure how to approach the fix for this problem without causing more errors. I did try re-adjusting the calculus done on the update method but it just caused more nonsense. I dont find productive posting all my attempts here because stackoverflow would say its too much code and because im not sure it would help with finding an answer.

参考

https://stackoverflow.com/a/21391448/2280645

import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ConnectedSliders {

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

    private static void createAndShowGUI() {
        JSlider s0 = new JSlider(0, 100, 30);
        JSlider s1 = new JSlider(0, 100, 40);
        JSlider s2 = new JSlider(0, 100, 30);

        SliderGroup sliderGroup = new SliderGroup();
        //sliderGroup.add(s0);
        //sliderGroup.add(s1);
        //sliderGroup.add(s2);

        JPanel panel = new JPanel(new GridLayout(0, 3));
        panel.add(s0);
        panel.add(createListeningLabel(s0));
        panel.add(createCheckBox(s0, sliderGroup));

        panel.add(s1);
        panel.add(createListeningLabel(s1));
        panel.add(createCheckBox(s1, sliderGroup));

        panel.add(s2);
        panel.add(createListeningLabel(s2));
        panel.add(createCheckBox(s2, sliderGroup));

        panel.add(createListeningLabel(s0, s1, s2));

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(panel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static JLabel createListeningLabel(final JSlider... sliders) {
        final JLabel label = new JLabel("");
        for (JSlider slider : sliders) {
            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    int sum = 0;
                    for (JSlider slider : sliders) {
                        sum += slider.getValue();
                    }
                    label.setText("Sum: " + sum);
                }
            });
        }
        return label;
    }

    private static JLabel createListeningLabel(final JSlider slider) {
        final JLabel label = new JLabel("");
        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                label.setText(String.valueOf(slider.getValue()));
            }
        });
        return label;
    }

    private static JCheckBox createCheckBox(final JSlider slider, SliderGroup group) {
        final JCheckBox checkBox = new JCheckBox();
        checkBox.setSelected(true);

        checkBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    group.add(slider);
                    slider.setEnabled(true);
                } else if(e.getStateChange() == ItemEvent.DESELECTED) {
                    group.remove(slider);
                    slider.setEnabled(false);
                }
            }
        });

        return checkBox;

    }

}

class SliderGroup {

    private final Map<JSlider, Integer> values;
    private final LinkedList<JSlider> candidates;

    private final ChangeListener changeListener;
    private boolean updating = false;

    SliderGroup() {
        this.values = new HashMap<JSlider, Integer>();
        this.candidates = new LinkedList<JSlider>();

        changeListener = new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                JSlider source = (JSlider) e.getSource();
                update(source);
            }
        };
    }

    private void update(JSlider source) {
        if (updating) {
            return;
        }
        updating = true;

        int delta = source.getValue() - values.get(source);
        if (delta > 0) {
            distributeRemove(delta, source);
        } else {
            distributeAdd(delta, source);
        }

        for (JSlider slider : candidates) {
            values.put(slider, slider.getValue());
        }

        updating = false;
    }

    private void distributeRemove(int delta, JSlider source) {
        int counter = 0;
        int remaining = delta;
        while (remaining > 0) {
            JSlider slider = candidates.removeFirst();
            counter++;

            if (slider == source) {
                candidates.addLast(slider);
            } else {
                if (slider.getValue() > 0) {
                    slider.setValue(slider.getValue() - 1);
                    remaining--;
                    counter = 0;
                }
                candidates.addLast(slider);
                if (remaining == 0) {
                    break;
                }
            }
            if (counter > candidates.size()) {
                String message = "Can not distribute " + delta + " among " + candidates;
                //System.out.println(message);
                //return;
                throw new IllegalArgumentException(message);
            }
        }
    }

    private void distributeAdd(int delta, JSlider source) {
        int counter = 0;
        int remaining = -delta;
        while (remaining > 0) {
            JSlider slider = candidates.removeLast();
            counter++;

            if (slider == source) {
                candidates.addFirst(slider);
            } else {
                if (slider.getValue() < slider.getMaximum()) {
                    slider.setValue(slider.getValue() + 1);
                    remaining--;
                    counter = 0;
                }
                candidates.addFirst(slider);
                if (remaining == 0) {
                    break;
                }
            }
            if (counter > candidates.size()) {
                String message = "Can not distribute " + delta + " among " + candidates;
                //System.out.println(message);
                //return;
                throw new IllegalArgumentException(message);
            }
        }
    }

    void add(JSlider slider) {
        candidates.add(slider);
        values.put(slider, slider.getValue());
        slider.addChangeListener(changeListener);
    }

    void remove(JSlider slider) {
        candidates.remove(slider);
        values.remove(slider);
        slider.removeChangeListener(changeListener);
    }

}

推荐答案

对链接到的示例进行较小的调整,这应该是可行的.

With a minor adjustment of the example that you linked to, this should be doable.

基本思想是不仅具有最初用于构造组的SliderGroup#addremove方法,而且还具有(除了添加/删除滑块之外)的addAndAdjustremoveAndAdjust方法.仅当一个滑块的值发生更改时,才使用最初调整滑块的相同方法来分配添加或删除的滑块的值.

The basic idea is to not only have the SliderGroup#add and remove methods that are used for constructing the group initially, but also addAndAdjust and removeAndAdjust methods that (in addition to adding/removing the slider) distribute the value of the slider that was added or removed, using the same methods that adjusted the sliders originally only when the value of one slider changed.

我还为复选框添加了keepOneSelected方法:如果可以禁用所有滑块,则没有任何滑块具有剩余的值.因此,该方法可确保至少一个复选框始终处于选中状态.

I also added a keepOneSelected method for the check boxes: If all sliders could be disabled, then there is none to have the remaining value. So the method makes sure that at least one of the check boxes remains always checked.

(根据评论中的讨论内容进行)

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ConnectedSlidersExt
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }

    private static void createAndShowGUI()
    {
        JSlider s0 = new JSlider(0, 100, 33);
        JSlider s1 = new JSlider(0, 100, 33);
        JSlider s2 = new JSlider(0, 100, 34);

        int expectedSum = 100;
        SliderGroup sliderGroup = new SliderGroup(expectedSum);
        sliderGroup.add(s0);
        sliderGroup.add(s1);
        sliderGroup.add(s2);

        JPanel panel =new JPanel(new GridLayout(0,3));
        panel.add(s0);
        panel.add(createListeningLabel(s0));
        JCheckBox checkBox0 = createCheckBox(s0, sliderGroup);
        panel.add(checkBox0);
        panel.add(s1);
        panel.add(createListeningLabel(s1));
        JCheckBox checkBox1 = createCheckBox(s1, sliderGroup);
        panel.add(checkBox1);
        panel.add(s2);
        panel.add(createListeningLabel(s2));
        JCheckBox checkBox2 = createCheckBox(s2, sliderGroup);
        panel.add(checkBox2);

        keepOneSelected(checkBox0, checkBox1, checkBox2);

        panel.add(createListeningLabel(s0, s1, s2));

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(panel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static void keepOneSelected(JCheckBox ...checkBoxes)
    {
        ActionListener actionListener = new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                int numSelected = 0;
                for (JCheckBox checkBox : checkBoxes)
                {
                    if (checkBox.isSelected())
                    {
                        numSelected++;
                    }
                }
                if (numSelected == 1)
                {
                    for (int i = 0; i < checkBoxes.length; i++)
                    {
                        JCheckBox checkBox = checkBoxes[i];
                        if (checkBox.isSelected())
                        {
                            checkBox.setEnabled(false);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < checkBoxes.length; i++)
                    {
                        JCheckBox checkBox = checkBoxes[i];
                        checkBox.setEnabled(true);
                    }
                }
            }
        };
        for (JCheckBox checkBox : checkBoxes)
        {
            checkBox.addActionListener(actionListener);
        }
    }

    private static JCheckBox createCheckBox(
        JSlider slider, SliderGroup group)
    {
        JCheckBox checkBox = new JCheckBox();
        checkBox.setSelected(true);
        checkBox.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                if (checkBox.isSelected())
                {
                    slider.setEnabled(true);
                    group.addAndAdjust(slider);
                }
                else
                {
                    slider.setEnabled(false);
                    group.removeAndAdjust(slider);
                }
            }
        });

        return checkBox;

    }

    private static JLabel createListeningLabel(final JSlider ... sliders)
    {
        final JLabel label = new JLabel("");
        for (JSlider slider : sliders)
        {
            slider.addChangeListener(new ChangeListener()
            {
                @Override
                public void stateChanged(ChangeEvent e)
                {
                    int sum = 0;
                    for (JSlider slider : sliders)
                    {
                        if (slider.isEnabled())
                        {
                            sum += slider.getValue();
                        }
                    }
                    label.setText("Sum: "+sum);
                }
            });
        }
        return label;
    }

    private static JLabel createListeningLabel(final JSlider slider)
    {
        final JLabel label = new JLabel("");
        slider.addChangeListener(new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent e)
            {
                label.setText(String.valueOf(slider.getValue()));
            }
        });
        return label;
    }


}


class SliderGroup
{
    private final int expectedSum;
    private final LinkedList<JSlider> candidates;

    private final ChangeListener changeListener;
    private boolean updating = false;

    SliderGroup(int expectedSum)
    {
        this.expectedSum = expectedSum;
        this.candidates = new LinkedList<JSlider>();

        changeListener = new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent e)
            {
                JSlider source = (JSlider)e.getSource();
                update(source);
            }
        };
    }

    private void update(JSlider source)
    {
        if (updating)
        {
            return;
        }
        updating = true;

        for (JSlider slider : candidates)
        {
            slider.setValueIsAdjusting(true);
        }

        if (candidates.size() > 1)
        {
            int delta = computeSum() - expectedSum;
            if (delta > 0)
            {
                distributeRemove(delta, source);
            }
            else
            {
                distributeAdd(delta, source);
            }
        }

        for (JSlider slider : candidates)
        {
            slider.setValueIsAdjusting(false);
        }

        updating = false;
    }


    private void distributeRemove(int delta, JSlider source)
    {
        int counter = 0;
        int remaining = delta;
        while (remaining > 0)
        {
            //System.out.println("remove "+remaining);

            JSlider slider = candidates.removeFirst();
            counter++;

            if (slider == source)
            {
                candidates.addLast(slider);
            }
            else
            {
                if (slider.getValue() > 0)
                {
                    slider.setValue(slider.getValue()-1);
                    remaining--;
                    counter = 0;
                }
                candidates.addLast(slider);
                if (remaining == 0)
                {
                    break;
                }
            }
            if (counter > candidates.size())
            {
                String message =
                    "Can not distribute " + delta + " among " + candidates;
                // System.out.println(message);
                // return;
                throw new IllegalArgumentException(message);
            }
        }
    }

    private void distributeAdd(int delta, JSlider source)
    {
        int counter = 0;
        int remaining = -delta;
        while (remaining > 0)
        {
            //System.out.println("add "+remaining);

            JSlider slider = candidates.removeLast();
            counter++;

            if (slider == source)
            {
                candidates.addFirst(slider);
            }
            else
            {
                if (slider.getValue() < slider.getMaximum())
                {
                    slider.setValue(slider.getValue()+1);
                    remaining--;
                    counter = 0;
                }
                candidates.addFirst(slider);
                if (remaining == 0)
                {
                    break;
                }
            }
            if (counter > candidates.size())
            {
                String message =
                    "Can not distribute " + delta + " among " + candidates;
                // System.out.println(message);
                // return;
                throw new IllegalArgumentException(message);
            }
        }
    }

    private int computeSum()
    {
        int sum = 0;
        for (JSlider slider : candidates)
        {
            sum += slider.getValue();
        }
        return sum;
    }

    void add(JSlider slider)
    {
        candidates.add(slider);
        slider.addChangeListener(changeListener);
    }

    void remove(JSlider slider)
    {
        candidates.remove(slider);
        slider.removeChangeListener(changeListener);
    }

    void addAndAdjust(JSlider slider)
    {
        add(slider);
        if (candidates.size() == 2)
        {
            update(candidates.get(0));
        }
        else
        {
            update(slider);
        }
    }

    void removeAndAdjust(JSlider slider)
    {
        remove(slider);
        update(slider);
        if (candidates.size() == 1)
        {
            JSlider candidate = candidates.get(0);
            int max = candidate.getMaximum();
            candidate.setValue(Math.min(max, expectedSum));
        }
    }


}

这篇关于多个JSlider激活和停用-共享值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆