简体   繁体   English

JTable单元格中的JComboBox。 选择更改会影响其他行中的JComboBox

[英]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. 我在这里看到了类似的问题,但不完全是这种情况:我有一个两列的JTable,第一列有一个JComboBox,第二列有一个整数。 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. JComboBox设置了ItemListener,以便在更改JComboBox中的选择时,将Integer列中的值设置为comboBox所选索引。 Right click on the table renders JPopupMenu with addRow() as MouseEvent. 右键单击该表将使用addRow()作为MouseEvent渲染JPopupMenu。

It works fine as long as I add all the rows I want when setting up the DefaultTableModel. 只要我在设置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. 但是,如果我仅以一行开始模型,并使用MouseEvent(或在DefaultTableModel的参数中添加行而不是添加行的任何其他方法)添加行,则当我们开始更改组合框中的选择时,它将更改其他行中的整数值。

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? 例如:如果我运行该程序并立即通过MouseEvent添加另外两行,则从第0行的组合中选择零,从第1行的组合中选择1,从第2行的组合中选择2。我回到第0行,并且一旦激活组合框(我还没有选择项目...),它就会将第2行中的整数更改为0。有人可以告诉我如何停止在此更改整数方式? 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 . 不要使用MouseListener来显示弹出菜单,不同的OS会对弹出窗口有不同的触发,并且并非所有触发都由mousePressed触发。 Instead use JComponent#setComponentPopupMenu and let the API deal with it 而是使用JComponent#setComponentPopupMenu并让API处理它
  • 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. 相反,使用模型的setValueAt方法可以决定更改第一列的值后该怎么做。

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);
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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