Java 在JComboBox中itemStateChanged时获取JTable的选定行

Java 在JComboBox中itemStateChanged时获取JTable的选定行,java,swing,jtable,jcombobox,Java,Swing,Jtable,Jcombobox,我试图在单击combox时获取当前行数据。 我的问题是,如果我试图在单击组合框时获取详细信息,则检索到的数据是错误的 这将填充集合中的无效数据。请按照下面提到的确切步骤进行复制 请运行代码以复制问题,因为它仅在初始选择期间有效,而在初始选择之后无效 注意:请仅在第二列中单击“直接” Step 1: Click on Second Column of Row 1 Step 2: Select- Item 1 Step 3: Click on Second Column of Row 2 Step

我试图在单击combox时获取当前行数据。 我的问题是,如果我试图在单击组合框时获取详细信息,则检索到的数据是错误的

这将填充集合中的无效数据。请按照下面提到的确切步骤进行复制

请运行代码以复制问题,因为它仅在初始选择期间有效,而在初始选择之后无效

注意:请仅在第二列中单击“直接”

Step 1: Click on Second Column of Row 1
Step 2: Select- Item 1 
Step 3: Click on Second Column of Row 2
Step 4: Select- Item 2
Step 5: Click on Second Column of Row 3
Step 6: Select- Item 3
WORKS Fine till here :)
Step 7 : Click on Second column of Row 1 and do not change an selection leave it as it is (Just click on the combobox twice)
Step 8 : Click on Second column of Row 2, DO NO CHANGES
Step 9 : Click on Second column of Row 3, DO NO CHANGES
Step 10: NOW randomly click on any of the second columns of rows(1,2,3) and see the output datamap. It really wierd why the event is
下面是示例代码:

import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class TestJCombo extends JFrame {

    public TestJCombo() {
        initialize();
    }

    JTable jTable;
    JComboBox comboBox;
    Map<Integer, String> dataMap;

    private void initialize() {
        setSize(300, 300);
        setLayout(new FlowLayout(FlowLayout.LEFT));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTextField field = new JTextField();
        field.setSize(50000, 25);
        field.setText("                                                                                           ");

        jTable = new JTable();

        comboBox = new JComboBox();
        comboBox.setEditable(true);
        comboBox.addItem("item 1");
        comboBox.addItem("item 2");
        comboBox.addItem("item 3");
        comboBox.setEditable(false);

        dataMap = new LinkedHashMap();

        comboBox.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {

                    Object selected = comboBox.getSelectedItem();

                    int selectedRow = jTable.getSelectedRow();
                    selectedRow = jTable.convertRowIndexToModel(selectedRow);
                    if (selectedRow != -1) {
                        String user = (String) jTable.getValueAt(selectedRow, 0);
                        String data = "Row: " + (selectedRow + 1) + " :::: " + user + " , "
                                + comboBox.getSelectedItem();
                        dataMap.put(selectedRow + 1, "[" + user + " - " + comboBox.getSelectedItem() + "]");
                        if (selected != null) {
                            field.setText(data);
                        }
                        System.out.println("Current data map:: " + dataMap);
                    }
                }

            }
        });

        jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jTable.setRowHeight(30);
        jTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

        DefaultTableModel myTableMdl = new DefaultTableModel();
        myTableMdl.addColumn("User");
        myTableMdl.addColumn("Role");
        jTable.setModel(myTableMdl);

        jTable.getColumn("Role").setCellEditor(new DefaultCellEditor(comboBox));

        Vector tableData;
        for (int i = 1; i <= 7; i++) {
            tableData = new Vector();
            tableData.add("User " + i);
            myTableMdl.addRow(tableData);
        }

        getContentPane().add(jTable);
        getContentPane().add(field);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestJCombo().setVisible(true);
            }
        });
    }
}
导入java.awt.Cursor;
导入java.awt.FlowLayout;
导入java.awt.event.ItemEvent;
导入java.awt.event.ItemListener;
导入java.util.LinkedHashMap;
导入java.util.Map;
导入java.util.Vector;
导入javax.swing.DefaultCellEditor;
导入javax.swing.JComboBox;
导入javax.swing.JFrame;
导入javax.swing.JTable;
导入javax.swing.JTextField;
导入javax.swing.ListSelectionModel;
导入javax.swing.SwingUtilities;
导入javax.swing.table.DefaultTableModel;
公共类TestJCombo扩展了JFrame{
公共测试jcombo(){
初始化();
}
JTable-JTable;
JComboBox组合框;
地图数据地图;
私有void初始化(){
设置大小(300300);
setLayout(新的FlowLayout(FlowLayout.LEFT));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
最终JTextField=新JTextField();
字段设置大小(50000,25);
字段。setText(“”);
jTable=新的jTable();
comboBox=新的JComboBox();
comboBox.setEditable(真);
组合框。附加项(“第1项”);
组合框。附加项(“第2项”);
组合框。附加项(“第3项”);
comboBox.setEditable(false);
dataMap=新建LinkedHashMap();
comboBox.addItemListener(新的ItemListener(){
公共无效itemStateChanged(ItemEvent e){
如果(如getStateChange()==ItemEvent.SELECTED){
所选对象=comboBox.getSelectedItem();
int selectedRow=jTable.getSelectedRow();
selectedRow=jTable.convertRowIndexToModel(selectedRow);
如果(selectedRow!=-1){
字符串用户=(字符串)jTable.getValueAt(selectedRow,0);
String data=“行:+(selectedRow+1)++”:“+user+”,”
+comboBox.getSelectedItem();
dataMap.put(selectedRow+1,“[”+user+“-“+comboBox.getSelectedItem()+”);
如果(已选择!=null){
field.setText(数据);
}
System.out.println(“当前数据映射::”+数据映射);
}
}
}
});
jTable.setSelectionMode(ListSelectionModel.SINGLE_选择);
jTable.设置行高(30);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_Cursor));
DefaultTableModel myTableMdl=新的DefaultTableModel();
myTableMdl.addColumn(“用户”);
myTableMdl.addColumn(“角色”);
jTable.setModel(myTableMdl);
getColumn(“角色”).setCellEditor(新的DefaultCellEditor(组合框));
矢量表格数据;

对于(int i=1;i问题在于,您正在创建一个
JComboBox
,然后将其放在列中的所有单元格上。您正在引用
JComboBox
,而不是为每个单元格创建一个新的。这就是为什么当您按照您提到的10个步骤操作时,得到的结果是非常愚蠢和毫无意义的

下面是修复方法,为列1(角色列)中的所有单元格创建一个自定义。目标是为每个单元格创建一个全新的
JComboBox
。这是通过将
JTable
的声明更改为
JTable=new JTable(){…};
来覆盖
getCellEditor(…){…}
method。另外,方法
private JComboBox createComboBox(){…}
是创建全新的
JComboBox
所需的

现在,我们将取出
addItemListener
并将其替换为
addActionListener
。这是必需的,因为如果用户选择了已选择的项目,则将不会调用
ItemListener
中的
itemStateChanged
。我们需要复制两次鼠标单击,其中一次用于显示下拉列表列表和第二个用于选择项目(如果不需要,可以跳过此步骤)

我还对您的代码进行了编辑,使其更具可读性和效率

以下是一个MVCE:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.table.TableCellEditor;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class TestJCombo extends JFrame {

    JTable jTable;
    //JComboBox comboBox;//not needed, replaced by the createComboBox() method.
    Map<Integer, String> dataMap;
    final JTextField FIELD = new JTextField(25);//must put this globally.
    //Since it is final, it should be all in upper case

    //It is a good practice to put the global variables on top and constructor(s) below.
    public TestJCombo() {
        initialize();
    }

    private void initialize() {
        //use pack(); instead setSize(...); I used it at the end of this method.
        //setSize(300, 300);
        setLayout(new FlowLayout(FlowLayout.LEFT));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        //both lines not needed, it has been taken care of when FIELD was declared.
        //FIELD.setSize(50000, 25);
        //FIELD.setText("                                         "
        //  + "                                                  ");

        //Must create a seperate TableCellEditor for each cell in the table.
        jTable = new JTable() {
            public TableCellEditor getCellEditor(int row, int column) {
                int modelColumn = convertColumnIndexToModel(column);
                //if the cell lies in the second column, create a custom cell editor.
                if (modelColumn == 1) {
                    return (TableCellEditor) new DefaultCellEditor(createComboBox());
                } else {
                    return super.getCellEditor(row, column);
                }
            }
        };

        //comboBox = new JComboBox();
        //comboBox.setEditable(true);
        //comboBox.addItem("item 1");
        //comboBox.addItem("item 2");
        //comboBox.addItem("item 3");
        //comboBox.setEditable(false);
        dataMap = new LinkedHashMap();

        jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jTable.setRowHeight(30);
        jTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

        DefaultTableModel myTableMdl = new DefaultTableModel();
        myTableMdl.addColumn("User");
        myTableMdl.addColumn("Role");
        jTable.setModel(myTableMdl);

        //we have our own custom CellEditor, this is not needed
        //jTable.getColumn("Role").setCellEditor(new DefaultCellEditor(comboBox));
        Vector tableData;
        for (int i = 1; i <= 7; i++) {
            tableData = new Vector();
            tableData.add("User " + i);
            myTableMdl.addRow(tableData);
        }

        //It is better practice to add everything to a 
        //panel and then add that panel to the frame.
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        panel.add(jTable);
        panel.add(Box.createRigidArea(new Dimension(0, 10)));//add some space
        panel.add(FIELD);
        getContentPane().add(panel, BorderLayout.CENTER);
        pack();//should use this.
    }

    private JComboBox createComboBox() {
        JComboBox comboBox = new JComboBox();
        comboBox.setEditable(true);
        comboBox.addItem("item 1");
        comboBox.addItem("item 2");
        comboBox.addItem("item 3");
        comboBox.setEditable(false);

        //Add an ActionListener so that it would also detect if the user selects
        //the same item. The itemStateChanged in the ItemListener will not be
        //invoked if the user selects the item that is already selected.
        comboBox.addActionListener(new ActionListener() {
            //To update the result everytime the user selects an item
            //(regardless if it was selected or not), we need to "mock"
            //a two-click operation. The first click will show the 
            //drop-down list to select from and the second will
            //allow the user to select the desired choice to be selected.
            boolean doubleClick = false;

            @Override
            public void actionPerformed(ActionEvent ae) {
                if (doubleClick) {
                    int selectedRow = jTable.getSelectedRow();
                    selectedRow = jTable.convertRowIndexToModel(selectedRow);
                    Object selected = comboBox.getSelectedItem();
                    if (selectedRow != -1 && selected != null) {
                        String user = (String) jTable.getValueAt(selectedRow, 0);
                        String data = "Row: " + (selectedRow + 1) + " :::: " + user + " , "
                            + comboBox.getSelectedItem();
                        dataMap.put(selectedRow + 1, "[" + user + " - "
                            + comboBox.getSelectedItem() + "]");
                        FIELD.setText(data);
                        System.out.println("Current data map:: " + dataMap);
                    }
                    doubleClick = false;
                }
                doubleClick = true;
            }
        });

//      comboBox.addItemListener(new ItemListener() {
//
//          public void itemStateChanged(ItemEvent e) {
//              if (e.getStateChange() == ItemEvent.SELECTED) {
//
//                  Object selected = comboBox.getSelectedItem();
//
//                  int selectedRow = jTable.getSelectedRow();
//                  selectedRow = jTable.convertRowIndexToModel(selectedRow);
//                  if (selectedRow != -1) {
//                      String user = (String) jTable.getValueAt(selectedRow, 0);
//                      String data = "Row: " + (selectedRow + 1) + " :::: " + user + " , "
//                          + comboBox.getSelectedItem();
//                      dataMap.put(selectedRow + 1, "[" + user + " - "
//                      + comboBox.getSelectedItem() + "]");
//                      if (selected != null) {
//                          FIELD.setText(data);
//                      }
//                      System.out.println("Current data map:: " + dataMap);
//                  }
//              }
//
//          }
//      });
        return comboBox;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestJCombo().setVisible(true);
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.table.TableCellEditor;
导入java.awt.Cursor;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
导入java.awt.event.ItemEvent;
导入java.awt.event.ItemListener;
导入java.util.LinkedHashMap;
导入java.util.Map;
导入java.util.Vector;
导入javax.swing.Box;
导入javax.swing.BoxLayout;
导入javax.swing.DefaultCellEditor;
导入javax.swing.JComboBox;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JTable;
导入javax.swing.JTextField;
导入javax.swing.ListSelectionModel;
导入javax.swing.SwingUtilities;
导入javax.swing.table.DefaultTableModel;
公共类TestJCombo扩展了JFrame{
JTable-JTable;
//JComboBox comboBox;//不需要,替换为createComboBox()方法。
地图数据地图;
final JTextField=newjtextfield(25);//必须全局放置此字段。
//因为它是最终的,所以应该都是大写的
//将全局变量放在上面,将构造函数放在下面是一个很好的实践。
公共测试jcombo(){
初始化();
}
私有void初始化(){
//使用pack();而不是setSize(…);我在这个方法的末尾使用了它。
//设置大小(3
selectedRow = jTable.convertRowIndexToModel(selectedRow);
...
    String user = (String) jTable.getValueAt(selectedRow, 0);
String user = (String) jTable.getModel().getValueAt(selectedRow, 0);