简体   繁体   中英

JComboBox in JTable cell. Selection change affects JComboBox in other rows

I have been lurking around here for a couple years or so, never needed to ask a question before because I have always found my answer in someone else's question. Thank you!

I guess the lurking has come to an end. I have seen similar questions but not exactly this situation on here: I have a 2 column JTable with a JComboBox in the first column, and an integer in the second column. JComboBox has ItemListener set up so that when the selection in the JComboBox is changed the value in the Integer column is set to the comboBox selected index. Right click on the table renders JPopupMenu with addRow() as MouseEvent.

It works fine as long as I add all the rows I want when setting up the DefaultTableModel. But, if I start the model with only one row and use the MouseEvent (or any other method of adding rows other than adding them in parameters of DefaultTableModel) to add rows, when we start changing the selections in the combo boxes it will change the integer values in other rows.

For example: If i run the program and immediately add two more rows via MouseEvent, I then select Zero from combo in row 0, One from combo in row 1, and Two from combo in row 2. All fine so far... Then I go back to row 0 and as soon as I activate the combobox (I haven't selected an item yet...) it changes the integer in row 2 to 0. Can anyone tell me how to stop the integers from changing in this manner? here is a trial code:

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class JComboBoxInJTable {

    public static void main(String[] args) {
        new JComboBoxInJTable();
    }

    public JComboBoxInJTable() {
        EventQueue.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            DefaultTableModel model = new DefaultTableModel(new Object[]{"ComboBox", "Index"}, 1);
            JTable table = new JTable(model);

            //popup menu to add row
            JPopupMenu popup = new JPopupMenu();
            JMenuItem newRow;
            newRow = new JMenuItem("New Row");
            newRow.setToolTipText("Add new row.");
            newRow.addActionListener((ActionEvent nr) -> {
                model.addRow(new Object[]{"", ""});
            });
            popup.add(newRow);

            //set up right-click to open popup menu
            table.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent rc) {
                    if (SwingUtilities.isRightMouseButton(rc)) {
                        if (table.getSelectedRow() >= 0) {
                            popup.show(table, rc.getX(), rc.getY());
                        }
                    }
                }
            });

            JComboBox combo = new JComboBox(new Object[]{"Zero", "One", "Two", "Three"});
            combo.addItemListener((ItemEvent e) -> {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    //sets value of cell to left of combobox to comboboxe's selected index
                    table.setValueAt(combo.getSelectedIndex(), table.getSelectedRow(), 1);
                } else {
                    //do nothing...
                }
            });

            DefaultCellEditor comboEditor = new DefaultCellEditor(combo);

            TableColumnModel tcm = table.getColumnModel();
            tcm.getColumn(0).setCellEditor(comboEditor);

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JScrollPane(table));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

As usual I am sure this is something simple that I am missing. Thanks Again for the help in the past and in the future!

  • Don't use MouseListener s to show popup menus, different OSs have different triggers for the popups, and not all are triggered by mousePressed . Instead use JComponent#setComponentPopupMenu and let the API deal with it
  • Don't modify the state of the model from an editor. This can place the model into an invalidate state and cause other side effects, like you have now. Once seems to be happening is when a new row is selected, the editor is been updated with the rows cell value, but the row selection hasn't been set, so the table still thinks the previous row is still selected. Instead, use the models setValueAt method to make decisions about what to do once the first columns value is changed.

For example...

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class JComboBoxInJTable {

    public static void main(String[] args) {
        new JComboBoxInJTable();
    }

    private List<String> comboData;

    public JComboBoxInJTable() {
        EventQueue.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            DefaultTableModel model = new DefaultTableModel(new Object[]{"ComboBox", "Index"}, 1) {

                @Override
                public void setValueAt(Object aValue, int row, int column) {
                    super.setValueAt(aValue, row, column);
                    if (column == 0) {
                        String value = aValue == null ? null : aValue.toString();
                        if (aValue == null) {
                            super.setValueAt(null, row, 1);
                        } else {
                            super.setValueAt(comboData.indexOf(aValue), row, 1);
                        }
                    }
                }

            };
            JTable table = new JTable(model);
            table.setFillsViewportHeight(true);
            table.setGridColor(Color.GRAY);

            //popup menu to add row
            JPopupMenu popup = new JPopupMenu();
            JMenuItem newRow;
            newRow = new JMenuItem("New Row");
            newRow.setToolTipText("Add new row.");
            newRow.addActionListener((ActionEvent nr) -> {
                model.addRow(new Object[]{"", ""});
            });
            popup.add(newRow);

            table.setComponentPopupMenu(popup);

            comboData = new ArrayList<>(Arrays.asList(new String[]{"Zero", "One", "Two", "Three"}));

            JComboBox combo = new JComboBox(comboData.toArray(new String[comboData.size()]));
//          combo.addItemListener((ItemEvent e) -> {
//              if (e.getStateChange() == ItemEvent.SELECTED) {
//                  //sets value of cell to left of combobox to comboboxe's selected index
//                  System.out.println("Selected row = " + table.getSelectedRow());
//                  table.setValueAt(combo.getSelectedIndex(), table.getSelectedRow(), 1);
//              } else {
//                  //do nothing...
//              }
//          });

            DefaultCellEditor comboEditor = new DefaultCellEditor(combo);

            TableColumnModel tcm = table.getColumnModel();
            tcm.getColumn(0).setCellEditor(comboEditor);

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JScrollPane(table));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM