Reverting the selection of JCombox - java

We are trying to implement a validation on the selections made with a JCombobox. In case of the new selection failing this validation, we are trying to revert to the previous selection.
Any idea about how could this be done?
I've created an implementation of ItemListener interface. Captured the previous value by checking for the DESELECTED event and validated the current selection after SELECTED event. But I'm not sure about where do I reset to the previous value when needed.
Can I do it from the listener itself?
Would that lead to recursive calls to my listener?

Can I do it from the listener itself ?
Yes you can. For instance:
JComboBox comboBox = new JComboBox();
comboBox.addItemListener(new ItemListener() {
Object previousSelection = null;
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.DESELECTED) {
previousSelection = e.getItem();
} else if(!isValid(e.getItem())) {
JComboBox cb = (JComboBox)e.getSource();
cb.setSelectedItem(previousSelection);
}
}
});
Where isValid(Object obj) method should validate selected item.
Would that lead to recursive calls to my listener ?
Sure but the previous selected item was valid so it will be called 2 times top:
First time when user attempts to select an invalid item.
Second time when listener sets the previous item as the selected one.

Related

How to delete a CheckBox from a TableView in JavaFX?

I'm writing a seating chart program using JavaFX. I have a table that keeps a list of students together that holds their name, grade, and whether they are present or absent (using a checkbox). I have a delete button that allows me to delete the students from the list. This works fine, however, whenever I delete the student object, the checkbox does not go along with it. I'm not sure what I would need to add to get that to work. Here is a snippet of the delete code. There are also two images below that show my problem. This is my first post so please let me know if I missed something. Please help! Thanks!
ObservableList<Student> items, sel;
items = currentTable.getItems();
sel = currentTable.getSelectionModel().getSelectedItems();
Student s = new Student("", "", 0, "");
for (Student p : sel) {
items.remove(p);
s = p;
}
Before Delete
After Delete
This has nothing to do with the delete or remove method. It has to do with what you did in TableColumn.setCellFactory().
To get the checkbox you shown, you should have used (in general) one of the two methods:
Overriding updateItem() in TableCell while setting Cell Factory
There is this empty parameter in updateItem() which indicates whether the row is empty or not. You need to use that to determine when not to show the checkbox.
column.setCellFactory(col -> {
return new TableCell<Foo, Boolean>() {
final CheckBox checkBox = new CheckBox();
#Override
public void updateItem(final Boolean selected, final boolean empty) {
super.updateItem(selected, empty);
if (!this.isEmpty()) {
setGraphic(checkBox);
setText("");
}
else {
setGraphic(null); // Remove checkbox if row is empty
setText("");
}
}
}
}
Using CheckBoxTableCell
JavaFX API has this convenient class CheckBoxTableCell that would do all these for you. Most people find this class hard to use because there are 2 things that you need to ensure to use it correctly:
The TableView that the column belongs to must be editable.
The TableColumn itself must be editable.
Example:
tableView.setEditable(true);
tableColumnSelected.setCellFactory(CheckBoxTableCell.forTableColumn(tableColumnSelected));
tableColumnSelected.setEditable(true);
As for whether which entry you want to be removed with the delete button, you just need to remove the correct items from the TableView.

Selection on one in an Array of JComboBoxes fires the action for all

I create an array of combo boxes in a for loop like so:
for(int i = 0; i < 5; i++) {
...
comboStudy[i] = new JComboBox(studyModel);
comboStudy[i].addActionListener(new studyListener());
comboStudy[i].setActionCommand("" + i);
...
}
The listener is an instance inner class:
public class studyListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
int i = Integer.parseInt(evt.getActionCommand());
// do some stuff that requires i and also access
// to the instance members of the containing class
}
}
The problem I now face is that whenever I make a selection at run time in comboStudy[0] the action event gets fired 5 times. The first time i is 4, decreasing each time until it gets to 0.
I also tried it using an ItemListener, but it has the same problem.
Please help!
This is because you are using the same ComboBoxModel in all of your JComboBoxes.
Each JComboBox is a listener of the ComboxBoxModel and the ComboBoxModel will notify each listener whenever there is a change to the data model. When you select an item in a JComboBox, the ComboBoxModel changes which in turn fires events to each JComboBox. This is why you see events occurring on each JComboBox.

Which radio button is selected in a button group

What can I do to get which radiobutton is selected on a buttongroup without doing this:
if (jRadioButton1.isSelected()) {
//...
}
if (jRadioButton2.isSelected()) {
//...
}
if (jRadioButton3.isSelected()) {
//...
}
if (jRadioButton4.isSelected()) {
//...
}
You can get the ButtonModel for the selected button via the getSelection() method of ButtonGroup. I don't know how you can avoid conditionally branching on the selected button though, unless you have some sort of ancillary data structure mapping from ButtonModel to actions to perform, for instance. If you had that, then you could just fire the action based on the returned ButtonModel.
Darryl's Select Button Group has a getSelectedButton() method.
I know the question was posted long back. Anyway, we can use the setActioncommand function. while creating the radio button, setActionCommand could be invoked to set the action command value, which could be used to refer to the radio button that was selected.
jRadioButton1.setActionCommand("jRadioButton1");
jRadioButton2.setActionCommand("jRadioButton2")
.
.
String button_name = ((JToggleButton.ToggleButtonModel)button_group.getSelection()).getActionCommand();
ButtonGroup class does not provide a method to identify the currently selected button (inherited from AbstractButton) in the group if that is your intention. It only has clearSelection() method to clear the selected state of all buttons in the group (with exception for JButton and JMenuItem which don't have select/deselect button state).
One solution I can think of is to use a special variable or field (AbstractButton, JRadioButton or JRadioButtonMenuItem if it is in a menu item) to identify which one is currently selected by updating it inside each AbstractButton's action listener method (make sure to validate user clicks since it can be triggered more than once!). Use the variable (by typecasting it - for AbstractButton only) in other method(s).
Other than that, nope...you will need to do conditional branching.
For dealing with a button group bg, you can get the buttons by calling the button group's getElements() method, and using that as the parameter for the Collections.list() method, just save the result in an arraylist. From there it is relatively simple to retrieve the correct button.
ArrayList<AbstractButton> arl = Collections.list(bg.getElements());
for (AbstractButton ab : arl) {
JRadioButton jrb = (JRadioButton) ab;
if (jrb.isSelected()) {
return jrb;
}
}

problem when implementing a selection listener in a JTable

I am developing a JTable with different rows. I would like to associate an event to the selection of a row in this table. I have used the following selection class to provide behaviour to the table selection:
public class TableSelectionListener implements ListSelectionListener{
public Integer item;
public TableSelectionListener(Integer item){
this.dialog = item;
}
public void valueChanged(ListSelectionEvent e) {
System.out.println("The row clicked is "+item);
}
}
When I create an instance of this table, sai tabletest, I have added the following piece of code:
tabletest.getSelectionModel().addListSelectionListener(new TableSelectionListener(tabletest.getSelectedRow());
The problem is that when I click on one row once, instead of retrieving the related message once, I retrieve the same message several times, suggesting that the actions repeated several times. For example:
The row clicked is 0
The row clicked is 0
The row clicked is 0
The row clicked is 0
Does anyone know where the problem may be?
Well, that's just normal.
Your selection listener is created with the value of tabletest.getSelectedRow() at its creation table (which is zero). And, as you never change the value of item in your listener, this listener fcan only display 0as a result.
If I were you, I wouold replace the valueChanged() method by something like (although it's untested and I remember strange things happens sometimes when mixing view and model row values) this :
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()) // added as sometimes, multiple events are fired while selection changes
System.out.println("The row clicked is "+e.getFirstIndex());
}
Firstly, it's perfectly normal to get multiple ListSelectionEvents, while the selection is being changed. You can use the getValueIsAdjusting method to determine when selection has ended (it will return false).
Secondly, there's no need to construct your TableSelectionListener with a row number. When your valueChanged method is called, you can get the index of the first/last selected row (remember it's possibly to select multiple rows in the table, unless you disable that) using e.getFirstIndex() and e.getLastIndex() respectively.
An easier way of doing it, is as follows:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
System.out.println("e...."+table.getSelectedRow());
}
});

Linking JComboBox & JTable

Requirement:
I have a list of strings displayed in the ComboBox. Each of these Strings can have some properties. These properties are displayed in PropertyTable. ComboBox's selected Item's properties are displayed in the table. In addition, we use PropertyTable for editing or setting property values to the selected item in the comboBox.
Problem:
The moment I de-select the comboBox Item,say item1, all the existing property values in the PropertyTable are set as new property values to item1. Again, when I select this item1 back, I should get above property values(i.e values before item1 is Deselected) back in to the PropertyTable?
Current Implementation Logic:
I am having TableCellListner for each PropertyTableCell, whenever cell content is changed, it takes the cell's new value and assigns this as new property value to the combo box's selected item. whenever new item is selected, table is refreshed with the selected Item's property values.
//before is Table initialization code
Action action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
TableCellListener table = (TableCellListener)e.getSource();
String selectedItem=(String)ComponentPropComboBox.getSelectedItem();
if(table.getColumn()==1 && selectedItem!=null)
{
Property property=propertyMap.get(selectedItem);
else if(table.getRow()==0)
{
property.setProperty("MIN_LENGTH", (String)table.getNewValue());
propertyMap.put(selectedItem, property);
}
else if(table.getRow()==1)
{
property.setProperty("STARTS_WITH_STRING", (String)table.getNewValue());
propertyMap.put(selectedItem, property);
}
}
}
};
TableCellListener tcl = new TableCellListener(PropertiesTable, action);
How do i implement this requirement by overcoming the above challenge?
PS:
TableCellListner is a Not a java generic library. You can view code and its explanation at the following links:
http://www.camick.com/java/source/TableCellListener.java
http://tips4java.wordpress.com/2009/06/07/table-cell-listener/
I believe the question is obvious! Pls do let me know if question is not clear.Thanks in advance for your help & donating the knowledge!
In the code that listens for JComboBox selections. At its start have it set a boolean that the item is being changed. Then have your table refresh code ignore events that come while the boolean is set. After you are finished refreshing then set the boolean back.

Categories

Resources