我试图在点击组合框时获取当前行数据。我的问题是,如果我试图在单击组合框时获取详细信息,则检索到的数据是错误的。
这是在集合中填充无效数据。请按照下面提到的确切步骤进行复制。
请运行代码以复制该问题,因为它只在初始选择期间工作,而不是之后。
注意:请仅在第二列中单击“直接”
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);
}
});
}
}
问题是您正在创建一个JComboBox
,然后将其放在列中的所有单元格上。您正在引用JComboBox
,而不是为每个单元格创建一个新的。这就是为什么当你按照你提到的10个步骤操作时,得到的结果是非常愚蠢和毫无意义的。
修复方法如下:为第1列(角色列)中的所有单元格创建一个自定义的TableCellEditor
。目标是为每个单元格创建一个全新的JComboBox
。这是通过将JTable
的声明更改为JTable=new-JTable(){…}
覆盖getCellEditor(…){...}
方法。另外,方法
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);
}
});
}
}
问题是您在错误的组件上使用了错误的侦听器。您不应该向组合框添加侦听器。使用编辑器的目的是编辑数据并更新TableModel
。您不应该引用组合框进行进一步处理。
因此,您应该将一个TableModelListener
添加到TableModel
中。然后,只要第2列中的值发生更改,就会生成一个TableModelEvent
。TableModelEvent
将包含已更改单元格的行/列信息。
你可以查看:JTable-
还要注意的是,您使用convertRowIndexToModel()方法不正确:
selectedRow = jTable.convertRowIndexToModel(selectedRow);
...
String user = (String) jTable.getValueAt(selectedRow, 0);
首先,如果对表视图进行了排序或筛选,您只需要担心行索引的转换。在提供的代码中,您也不需要这样做,因此不需要转换索引。
但是,如果你曾经过滤过视图,那么你需要将视图行转换为模型行,然后你必须从模型中访问数据,而不是视图。所以代码是:
String user = (String) jTable.getModel().getValueAt(selectedRow, 0);
问题内容: 我正在使用带有ItemListener的JComboBox。更改值后,itemStateChanged事件将被调用两次。第一次调用,ItemEvent显示所选的原始项目。第二次显示正在由用户选择的项目。这是一些测试器代码: 因此,当我将组合框从“一个”更改为“三个”时,控制台显示: 我有没有办法告诉我使用ItemEvent,它是第二个项目(即用户选择的项目)?如果有人可以解释为什么两次
我想要一个始终可见的和es。单击“我的代码未更新”框中的“我的代码未更新”。
我创建了一个带有JComboBox CellEditor列的JTable。很好。然而,当我试图通过组合框检索所选值时,我只得到鼠标在特定行中选择的值。我似乎无法按每行获取所选值。这是我的代码:
我有一个JComboBox选择项目的问题,有人能帮我吗?我已经实现了一个图形用户界面窗口,其中有各种文本字段和一个JComboBox。当我点击按钮,代码必须创建一个对象与字符串的文本字段和字符串的ComboBox,但我有一个在...获取的代码是: 我也试过: 但是不要工作!我不知道我是否需要一个ActionListener,但我认为这不是必需的。
我试图通过数据的selectedRow从jTable到jTextField和jComboBox。 对于jTextField的每一行,我选择它会自动填充jTextFields,但对于jComboBox部分,当我选择一行时,它会正确填充,但当我选择另一行时,它会保留第一个选定的数据,我想传递任何选定行的数据:
问题内容: 我不知道如何在特定行中设置一个jcombobox …现在我已经为所有行设置了这个jcombobox,但是我只希望在一行中设置它: 问题答案: 更新: 在测试我的(可能是不完整的)答案时,我遇到了一个非常好的SO问题,我认为它将比我能提供的更好:将JComboBox放入JTable 另一个更新: 我再次阅读了您的问题,并且意识到您要求输入 特定的行 。我能想到的唯一方法是创建一个自定义C