I have three JCheckBox like following:
final JCheckBox c1 = new JCheckBox("A");
final JCheckBox c2 = new JCheckBox("B");
final JCheckBox c3 = new JCheckBox("C");
I make a group by ButtonGroup for this checkboxes like following:
final ButtonGroup bg = new ButtonGroup();
bg.add(c1);
bg.add(c2);
bg.add(c3);
I have a Button to display selected items into a label like following:
String SelectedItem="";
Enumeration<AbstractButton> items= bg.getElements();
while (items.hasMoreElements()) {
AbstractButton btn = items.nextElement();
if(btn.isSelected())
{
SelectedItem+=btn.getText()+",";
}
}
lblA.setText(SelectedItem);
this work fine , but i cann't select multiple check boxes in run time.
The purpose of ButtonGroup is multiple-exclusive selection. Do not create ButtonGroup only if you want to have a collection of your buttons. Instead of ButtonGroup use a standard collection like ArrayList.
List<JCheckBox> buttons = new ArrayList<>();
buttons.add(c1);
buttons.add(c2);
buttons.add(c3);
...
for ( JCheckbox checkbox : buttons ) {
if( checkbox.isSelected() )
{
SelectedItem += btn.getText() + ",";
}
}
Further notices: do updates (.setText) in Swing event thread (invokelater), remeber that it is better to create StringBuilder in such concatenation, but with UI component quantities like this, performance impact propably will be not noticeable.
From documentation:
Class ButtonGroup
This class is used to create a multiple-exclusion scope for a set of
buttons. Creating a set of buttons with the same ButtonGroup object
means that turning "on" one of those buttons turns off all other
buttons in the group.
That said, you probably are using the wrong class to do what you need, if you want to GROUP those checkboxes, put them in a panel, than you can work visibility, position and all other attributes with the panel instead of each checkbox.
Here is the link to documentation: Link
Related
I am working with vaadin 8.1.0 grid. I need to insert checkbox as a column and also as column header. when I click checkbox in column header, all column checkbox should be checked. That is working fine. But the problem is if I have 100 rows, when I Check header checkbox only some column checkboxes are checked i.e, only the rows that are displayed. When I scrolldown the remaining rows checkboxes are not checked. Here is my code:
List<Person> people = new ArrayList();
for (int i = 0; i < 1000; i++) {
people.add(i, new Person("Galileo Galilei", 1564));
}
CheckBox CheckBox1 = new CheckBox("All");
CheckBox1.setValue(false);
Grid<Person> grid = new Grid<>();
grid.setItems( people);
grid.addColumn(Person::getName).setCaption("Name");
grid.addColumn(Person::getYear).setCaption("Year of birth").setId("1");
grid.addComponentColumn(Person -> {
CheckBox chk=new CheckBox("Chk 2");
CheckBox1.addValueChangeListener(e->
chk.setValue(CheckBox1.getValue())
);
return chk;
}).setCaption("ch2").setId("CH2");
grid.getHeaderRow(0).getCell("CH2").setComponent( CheckBox1);
Well, for performance reasons, not all of the checkboxes are rendered from the start, as you'll see in the GIF below (right side, items flashing in violet), just the ones currently visible. And when you scroll, new items will be replacing the old ones, and checkboxes will be drawn for them. However their initial state will be uncheked, so the simplest solution is to set its initial state to the one of the master checkbox: CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());.
Result:
Furthermore, looking at the code you might have a minor leak. Since the checkboxes are drawn each time you scroll a larger section, the code in grid.addComponentColumn will be called each time, and value change listeners will be added to the list on and on and on... because they're never unregistered. Take a look at the image below, after a few scrolls, I ended up with over 9000 of them:
To overcome this, you can un-register the listeners when the checkboxes are detached:
grid.addComponentColumn(Person -> {
CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
// save the registration info to unregister at a later time
Registration listenerRegistration = CheckBox1.addValueChangeListener(e -> chk.setValue(CheckBox1.getValue()));
// when the checkbox is detached, remove the listener
chk.addDetachListener(event -> listenerRegistration.remove());
return chk;
}).setCaption("ch2").setId("CH2");
Now the list contains just those who were not yet detached:
You could also extend data model by a boolean field "selected" or wrap it into a new class and there add the "selected" field. Then set/unset that field in the ValueChangeListener added to the CheckBox.
This will also take care of selecting all grid entries and not just the one rendered. You will just have to change "selected" in all you data model instances.
Another approach would be to use the ImageRenderer. Then you wouldn't have to deal with any listeners.
This assumes that your model has an attribute to hold the value of checked/selected.
ThemeResource resourceChecked = new ThemeResource("selected.gif");
ThemeResource resourceUnchecked = new ThemeResource("deselected.gif");
grid.addColumn(person -> person.getSelected() ? resourceChecked : resourceUnchecked,
new ImageRenderer<>(event -> {
Person person = event.getItem();
person.setSelected(!person.getSelected());
grid.getDataProvider().refreshItem(person);
grid.markAsDirty();
}));
My GUI
I need some kind of foreach loop to go through all of the components in the content pane and add the values into a map.
HashMap<String, String> items = new HashMap<String, String>();
The String from the Drop Down box will be the Key and the value will be the contents of the Day and Week JTextField components (maybe with a ';' so I can split later).
So far I can't figure out how to link the components together or if that is even possible (even if there is a hacky way around it).
Assuming that all your components are inside JPanel you can try this:
for(Component comp : jPanel1.getComponents()){
if(comp instanceof JComboBox){
JComboBox cb = (JComboBox)comp;
System.out.println("cb.getName() = "+cb.getName());
System.out.println("cb.getSelectedItem() = "+cb.getSelectedItem());
}
}
In my form I've created JSpinner and JComboBox elements. Depending on the changing of JComboBox I have to use the different Spinner models. So in ComboBox listener I write spinner = new JSpinner(newModel), but it change nothing on form.
How to recreate element to see the difference?
// Create default Spinner
count = new JSpinner();
// Trying to replace spinner
product.addActionListener(e -> {
JComboBox source = (JComboBox) e.getSource();
String selectedItem = (String) source.getSelectedItem();
...
SpinnerNumberModel numberModel = getNewNumberModel(...)
count = new JSpinner(numberModel);
count.setModel(numberModel);
// repaint(); revalidate() - also don't working
});
You should not reallocate the spinner every time. Just replace its model. You are allocating a new instance of JSpinner in you action listener and change its model. But this new instance is not part of your panel and not visible. Remove count = new JSpinner(numberModel); from the action listener. And change the model of the existing spinner.
Is there another way to remove all items of a JComboBox then removeAllItems()? I use 2 JComboBoxes in mij app and when you select an item from the first combobox the related items should then be shown in the second combobox. When I do this, the items just keep appending after the ones that were already there. When I then first try to clear the combobox by using removeAllItems(), the second combobox is empty and stays empty whenever I change the first combobox... The first combobox keeps all its values... Does anyone see my problem?
festival is the JComboBox:
private JComboBox festival;
private JComboBox zone;
...
public void fillFestivalList(){
festival.removeAllItems();
List festivals = OP.fillFestivalList();
for(Object fest: festivals)
festival.addItem(fest.toString());
}
public void fillZoneList(String festival){
zone.removeAllItems();
List zones = OP.fillZoneList(festival);
for(Object zoneItem: zones)
zone.addItem(zoneItem.toString());
}
Regarding,
Is there another way to remove all items of a JComboBox then removeAllItems()?
Simply give the JComboBox a new model.
I would create a new DefaultComboBoxModel<T>, fill it with the newest entries, and then call setModel(...) on my JComboBox, passing in the new model when desired.
You can also Remove all the items in this way ,
but better to Give JCombobox a new DefaultComboBoxModel like the way #Hovercraft Full Of Eels said
int itemCount = combo.getItemCount();
for(int i=0;i<itemCount;i++){
combo.removeItemAt(0);
}
I have two JList on a swing GUI. Now I want that when a user clicks on a button (say TransferButton) the selected elements from one JList is added from the first JList to the second JList and remove those selected elements from the first JList.
The model doesn't know about selection.
The JList provides several methods to get the selected item or selected index. Use those methods to get the items and add them to the other list's model.
You have two JLists, then you also have their respective ListModels. Depending on how you implemented them you can just remove the elements from one model and add them to the other. Note, though, that the ListModel interface doesn't care for more than element access by default, so you probably have to implement add and remove methods there by yourself.
DefaultListModel leftModel = new DefaultListModel();
leftModel.addElement("Element 1");
leftModel.addElement("Element 2");
leftModel.addElement("Element 3");
leftModel.addElement("Element 5");
leftModel.addElement("Element 6");
leftModel.addElement("Element 7");
JList leftList = new JList(leftModel);
DefaultListModel rightModel = new DefaultListModel();
JList rightList = new JList(rightModel);
Let's imagine you have two JList components as described in the code above (left and right). You must write following code to transfer selected values from the left to the right JList.
for(Object selectedValue:leftList.getSelectedValuesList()){
rightModel.addElement(selectedValue);
leftModel.removeElement(selectedValue);
}