Multiple JSliders activating and deactivating - Sharing values
Context
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.
Primary Issue
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).
Preliminary Solution
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.
How to?
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.
References
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);
}
}
java swing awt jslider
add a comment |
Context
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.
Primary Issue
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).
Preliminary Solution
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.
How to?
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.
References
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);
}
}
java swing awt jslider
add a comment |
Context
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.
Primary Issue
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).
Preliminary Solution
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.
How to?
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.
References
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);
}
}
java swing awt jslider
Context
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.
Primary Issue
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).
Preliminary Solution
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.
How to?
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.
References
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);
}
}
java swing awt jslider
java swing awt jslider
edited Nov 26 '18 at 2:26
apandey846
9131019
9131019
asked Nov 21 '18 at 16:15
KenobiShanKenobiShan
2341526
2341526
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
With a minor adjustment of the example that you linked to, this should be doable.
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.
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.
(Edited based on the discussion in the comments:)
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));
}
}
}
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
|
show 12 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416274%2fmultiple-jsliders-activating-and-deactivating-sharing-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
With a minor adjustment of the example that you linked to, this should be doable.
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.
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.
(Edited based on the discussion in the comments:)
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));
}
}
}
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
|
show 12 more comments
With a minor adjustment of the example that you linked to, this should be doable.
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.
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.
(Edited based on the discussion in the comments:)
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));
}
}
}
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
|
show 12 more comments
With a minor adjustment of the example that you linked to, this should be doable.
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.
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.
(Edited based on the discussion in the comments:)
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));
}
}
}
With a minor adjustment of the example that you linked to, this should be doable.
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.
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.
(Edited based on the discussion in the comments:)
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));
}
}
}
edited Nov 25 '18 at 21:34
answered Nov 21 '18 at 19:46
Marco13Marco13
42.4k857108
42.4k857108
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
|
show 12 more comments
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
Marco, some bugs are happening with that code. For example, when Having 3 sliders with the values {33,33,34} if you mess a bit with the sliders, some errors come up. Can you help me ? please
– KenobiShan
Nov 25 '18 at 1:04
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
I added a bounty as a thanks for the help. But I really need to fix this code.
– KenobiShan
Nov 25 '18 at 1:06
1
1
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
When there are three sliders and they should sum up to 100, then disabling 2 of them (via their checkbox) should also disable the last one: It has to stay at 100, otherwise the sum will not be 100 any more. I edited the example to handle this case.
– Marco13
Nov 25 '18 at 16:12
1
1
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
When it should remain enabled, what should happen if its value is set to 50? Then the sum will no longer be 100....
– Marco13
Nov 25 '18 at 16:40
1
1
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
It's still not clear. Imagine you have 3 sliders, with values 33,33,34. Then 2 of them are disabled, therefore the last one will have a value of 100 then. Now you change this value to 50. Then you enable the first slider. What should the result be?
– Marco13
Nov 25 '18 at 16:46
|
show 12 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416274%2fmultiple-jsliders-activating-and-deactivating-sharing-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown