I added a JComboBox to a JTable:
table.getColumnModel().getColumn(16).setCellEditor(new DefaultCellEditor(c = new JComboBox()));
c.addItemListener(new CItemListener());
The Listener is fired when (de)selecting an Item. That's fine. My problem is however, that say: I've got "B" selected in one rows combobox, and "A" in another. When I have the combobox + row of "B" selected and now select the row with "A", the Listener is fired with Item "B" deselected and "A" selected, although I did not change the selection by itself. This is only true if I click on a combobox(without changing selection), not if I select the row somewhere else.
Can this behaviour be changed? If so: how?
Goal: Listener is only fired when a selection is made, not when the combobox is de/selected without changing an item.
Listener:
@Override
public void itemStateChanged(ItemEvent ie) {
String s = "";
if (ie.getStateChange() == ItemEvent.SELECTED){
if (table.getSelectedRow() != -1){
s = table.getModel().getValueAt(table.convertRowIndexToModel(table.getSelectedRow()), 1) );
anotherTable.increaseCountFor(s);
}
} else if (ie.getStateChange() == ItemEvent.DESELECTED){
if (table.getSelectedRow() != -1){
s = table.getModel().getValueAt(table.convertRowIndexToModel(table.getSelectedRow()), 1) );
anotherTable.decreaseCountFor(s);
}
}
Problems with your current approach
As you are listening to itemStateChanged
of Combobox it will be called for all rows even if one row is changed,as it is an expected behavior.[Try putting a print statement in that listener to see this]
There is no need to listen to combobox change what you want to listen in column change of the table
As you are incrementing based on some value of combobox values.I came up with the following solution.
There is a mainTable
in which 2nd column[index 1] is a dropdown.
Whenever the combobox value changed for any row in mainTable
the oldvalue is decremented and newvalue ins incremented in a counterTable
.
I have overridden the DefaultTableModel so that whenever the setValue is called it will check whether it is our desired column and if so it will do a decrement for old value and increment for new value in the counter table
Just run the below SSCCE code and select values from second column and see the changes
The following does what you've asked for
import java.awt.BorderLayout;
import java.util.Objects;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TableDropDown extends JFrame {
private JComboBox jComboBox1;
private JTable mainTable = new JTable();
private JTable counterTable = new JTable();
public TableDropDown() {
initialize();
}
private void initialize() {
//Loading the mainTable with sample values
DefaultTableModel model = new DefaultTableModel(new Object[][]{
{"Test", null, null},
{"Type", null, null},
{"What", null, null},
{"Which", null, null}
},
new String[]{
"Title 1", "Title 2", "Title 3"
}) {
@Override
//Main part that does the trick
public void setValueAt(Object newValue, int row, int column) {
//check if this is our column
if (column == 1) {
Object oldvalue = getValueAt(row, column);
if (!Objects.equals(newValue, oldvalue)) {
if (oldvalue != null) {
decreaseCountFor(oldvalue.toString());
}
increaseCountFor(newValue.toString());
}
}
super.setValueAt(newValue, row, column);
}
};
mainTable.setModel(model);
//loading counterTable and combobox sample values A to J
String[] contents = new String[10];
DefaultTableModel cModel = new DefaultTableModel(null,
new String[]{"Type", "Count"});
for (int i = 0; i < 10; i++) {
contents[i] = "" + (char) (i + 65);
cModel.addRow(new Object[]{contents[i], 0});
}
counterTable.setModel(cModel);
counterTable.setEnabled(false);//to disable editing
jComboBox1 = new JComboBox(new DefaultComboBoxModel(contents));
//setting cellEditor for Column 1
mainTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jComboBox1));
//stuffs to add value to frame
add(new javax.swing.JScrollPane(mainTable), BorderLayout.CENTER);
add(new javax.swing.JScrollPane(counterTable), BorderLayout.EAST);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public int getRowForValue(String val) {
for (int i = 0; i < counterTable.getRowCount(); i++) {
if (counterTable.getValueAt(i, 0).equals(val)) {
return i;
}
}
return -1;
}
public int getPrevoiusValue(int row) {
return Integer.parseInt(counterTable.getValueAt(row, 1).toString());
}
public void increaseCountFor(String x) {
int row = getRowForValue(x);
counterTable.setValueAt(getPrevoiusValue(row) + 1, row, 1);
}
public void decreaseCountFor(String x) {
int row = getRowForValue(x);
counterTable.setValueAt(getPrevoiusValue(row) - 1, row, 1);
}
public static void main(String[] args) {
new TableDropDown().setVisible(true);
}
}