Search code examples
javaeclipseuser-interfacejslider

link two JSliders using a checkbox


I´m working on a java GUI and I have two JSliders that I want to connect, using a checkbox. Specifically, when the checkbox is checked and I slide one of the sliders in one direction, I want the other slider to go in the opposite direction. Both sliders go from -5 to +5 and their default is 0. Unfortunately, I have no idea how to do that and I couldn´t find any solution to this problem so far. This is the Code so far. I´d really appreciate any kind of help regarding this.

JSlider sliderFilter1 = new JSlider(-5, 5, 0);
    sliderFilter1.setPaintTicks(true);
    sliderFilter1.setMajorTickSpacing(1);
    sliderFilter1.setBounds(10, 459, 200, 32);
    add(sliderFilter1);

    JSlider sliderFilter2 = new JSlider(-5, 5, 0);
    sliderFilter2.setMajorTickSpacing(1);
    sliderFilter2.setPaintTicks(true);
    sliderFilter2.setBounds(10, 503, 200, 32);
    add(sliderFilter2);

    JCheckBox chckbxConnectSlider = new JCheckBox("Connect Slider");
    chckbxConnectSlider.setBounds(6, 547, 131, 23);
    add(chckbxConnectSlider);

Solution

  • By using a ChangeListener you can code one slider to update the other based on it's value as it changes.

    final JSlider sliderFilter1;
    final JSlider sliderFilter2;
    final JCheckBox chckbxConnectSlider;
    
    sliderFilter1 = new JSlider(-5, 5, 0);
    sliderFilter1.setPaintTicks(true);
    sliderFilter1.setMajorTickSpacing(1);
    sliderFilter1.setBounds(10, 459, 200, 32);
    add(sliderFilter1);
    
    sliderFilter2 = new JSlider(-5, 5, 0);
    sliderFilter2.setMajorTickSpacing(1);
    sliderFilter2.setPaintTicks(true);
    sliderFilter2.setBounds(10, 503, 200, 32);
    add(sliderFilter2);
    
    chckbxConnectSlider = new JCheckBox("Connect Slider");
    chckbxConnectSlider.setBounds(6, 547, 131, 23);
    add(chckbxConnectSlider);
    
    sliderFilter1.addChangeListener(new ChangeListener() {
        private int lastValue = 0;
        @Override
        public void stateChanged(ChangeEvent e) {
            JSlider source = (JSlider) e.getSource();
            if (lastValue != ((int) source.getValue()) && chckbxConnectSlider.isSelected()) {
                lastValue = (int) source.getValue();
                sliderFilter2.setValue(-((int) source.getValue()));
            }
        }
    });
    sliderFilter2.addChangeListener(new ChangeListener() {
        private int lastValue = 0;
        @Override
        public void stateChanged(ChangeEvent e) {
            JSlider source = (JSlider) e.getSource();
            if (lastValue != ((int) source.getValue()) && chckbxConnectSlider.isSelected()) {
                lastValue = (int) source.getValue();
                sliderFilter1.setValue(-((int) source.getValue()));
            }
        }
    });
    

    Note that the components must be declared final so they can be accessed from the anonymous functions.

    Update: @MadProgrammer is right in saying this will cause some issues with recursion (well that's embarrassing). I've updated the code to perform checking on whether or not the value actually needs to be changed. It's also a good idea to use an actual layout manager instead of laying out the components by position. See Oracle's A Visual Guide to Layout Managers.