在 Jtable 单元格中单击 JComboBox 时调用 ActionPerformed
ActionPerformed being called when JComboBox is clicked in Jtable cell
我在 Jtable
单元格中使用 JComboBox
。当我单击 JComboBox
和 select 中的一个值时,它会调用 ActionPerformed
函数。到这里为止一切正常,但是当我再次单击 JComboBox
时,它会调用 ActionPerformed
函数,但它不应该这样做。我想要的是,当项目在 JComboBox
中 select 时调用 ActionPerformed
函数。换句话说,它应该像第一次使用 select 从 JComboBox
编辑项目然后调用 ActionPerformed
函数时一样工作。我不知道为什么会出现这个问题。这是我查看过的链接,我也进行了一些其他搜索,但仍然找不到上述问题的任何相关答案。
- Adding JComboBox to a JTable cell
- How to use ActionListener on a ComboBox to give a variable a value
- https://coderanch.com/t/339842/java/ComboBox-ItemListener-calling
这是代码,你可以复制粘贴查看。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class TableExample implements ActionListener{
JFrame frame;
JComboBox skuNameComboBoxTable;
TableExample() {
frame = new JFrame();
String data[][] = {{"101", "Amit", "Choose"},
{"102", "Jai", "Choose"},
{"101", "Sachin", "Choose"}};
String column[] = {"ID", "Name", "Degree"};
JTable table = new JTable(data, column);
table.setBounds(30, 40, 200, 300);
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane);
frame.setSize(300, 400);
frame.setVisible(true);
String[] array = {"BS(SE)", "BS(CS)", "BS(IT)"};
skuNameComboBoxTable = new JComboBox(array);
skuNameComboBoxTable.addActionListener(this);
TableColumn col = table.getColumnModel().getColumn(2);
col.setCellEditor(new DefaultCellEditor(skuNameComboBoxTable));
}
public static void main(String[] args) {
new TableExample();
}
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "actionPerformed called");
}
}
请告诉我为什么会出现这个问题,我该如何解决。
您可以尝试使用 ItemListener 并根据 ItemEvent 过滤您的操作。
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class JComboBoxTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] items = {"One", "Two", "Three"};
JComboBox cb = new JComboBox(items);
cb.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("Selected " + e.getItem());
} else {
System.out.println("Deselected " + e.getItem());
}
}
});
frame.add(cb);
frame.pack();
frame.setVisible(true);
}
}
不幸的是,在使用 DefaultCellEditor 时您不能做太多事情 - 这就是它的行为方式。在您的代码中,您可以添加检查以确保在处理事件之前发生了值的更改。如下所示:
public void actionPerformed(ActionEvent e) {
if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
JOptionPane.showMessageDialog(null, "actionPerformed called: ");
skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
发生这种情况是因为您对第 2 列使用了与 DefaultCellEditor 相同的 JComboBox。
每当您单击第 2 列中的单元格时,组合框将更改为当前单元格上的值并触发 DESELECT(旧值)和 SELECT(新值)。 只有当旧值和新值不同时才会发生这种情况。
避免这种情况的一种方法是在您正在使用的 DefaultCellEditor 上添加一个 CellEditorListener,如下所示:
TableColumn col = table.getColumnModel().getColumn(2);
DefaultCellEditor cellEditor = new DefaultCellEditor(skuNameComboBoxTable);
col.setCellEditor(cellEditor);
cellEditor.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
System.out.println("Value of combo box defined!");
}
@Override
public void editingCanceled(ChangeEvent e) {
System.out.println("Edition canceled, set the old value");
}
});
这样您就可以仅在 ComboBox 定义了值时执行操作。
希望对您有所帮助。
您不应该为此使用 ActionListener。当一个项目被选中时,组合框使用它自己的 ActionListener 来更新 TableModel。
因此,您应该监听 TableModel 中的更改,以便执行您的自定义代码。所以你应该使用 TableModelListener
来监听数据的变化。但是,即使只是开始和停止编辑单元格,TableModelListener
也可以触发事件,这对您来说可能是个问题。
在这种情况下你可以使用Table Cell Listener。它只会在 TableModel 中的值发生变化时生成事件。
我在 Jtable
单元格中使用 JComboBox
。当我单击 JComboBox
和 select 中的一个值时,它会调用 ActionPerformed
函数。到这里为止一切正常,但是当我再次单击 JComboBox
时,它会调用 ActionPerformed
函数,但它不应该这样做。我想要的是,当项目在 JComboBox
中 select 时调用 ActionPerformed
函数。换句话说,它应该像第一次使用 select 从 JComboBox
编辑项目然后调用 ActionPerformed
函数时一样工作。我不知道为什么会出现这个问题。这是我查看过的链接,我也进行了一些其他搜索,但仍然找不到上述问题的任何相关答案。
- Adding JComboBox to a JTable cell
- How to use ActionListener on a ComboBox to give a variable a value
- https://coderanch.com/t/339842/java/ComboBox-ItemListener-calling
这是代码,你可以复制粘贴查看。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
public class TableExample implements ActionListener{
JFrame frame;
JComboBox skuNameComboBoxTable;
TableExample() {
frame = new JFrame();
String data[][] = {{"101", "Amit", "Choose"},
{"102", "Jai", "Choose"},
{"101", "Sachin", "Choose"}};
String column[] = {"ID", "Name", "Degree"};
JTable table = new JTable(data, column);
table.setBounds(30, 40, 200, 300);
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane);
frame.setSize(300, 400);
frame.setVisible(true);
String[] array = {"BS(SE)", "BS(CS)", "BS(IT)"};
skuNameComboBoxTable = new JComboBox(array);
skuNameComboBoxTable.addActionListener(this);
TableColumn col = table.getColumnModel().getColumn(2);
col.setCellEditor(new DefaultCellEditor(skuNameComboBoxTable));
}
public static void main(String[] args) {
new TableExample();
}
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "actionPerformed called");
}
}
请告诉我为什么会出现这个问题,我该如何解决。
您可以尝试使用 ItemListener 并根据 ItemEvent 过滤您的操作。
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class JComboBoxTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] items = {"One", "Two", "Three"};
JComboBox cb = new JComboBox(items);
cb.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("Selected " + e.getItem());
} else {
System.out.println("Deselected " + e.getItem());
}
}
});
frame.add(cb);
frame.pack();
frame.setVisible(true);
}
}
不幸的是,在使用 DefaultCellEditor 时您不能做太多事情 - 这就是它的行为方式。在您的代码中,您可以添加检查以确保在处理事件之前发生了值的更改。如下所示:
public void actionPerformed(ActionEvent e) {
if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
JOptionPane.showMessageDialog(null, "actionPerformed called: ");
skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
发生这种情况是因为您对第 2 列使用了与 DefaultCellEditor 相同的 JComboBox。
每当您单击第 2 列中的单元格时,组合框将更改为当前单元格上的值并触发 DESELECT(旧值)和 SELECT(新值)。 只有当旧值和新值不同时才会发生这种情况。
避免这种情况的一种方法是在您正在使用的 DefaultCellEditor 上添加一个 CellEditorListener,如下所示:
TableColumn col = table.getColumnModel().getColumn(2);
DefaultCellEditor cellEditor = new DefaultCellEditor(skuNameComboBoxTable);
col.setCellEditor(cellEditor);
cellEditor.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
System.out.println("Value of combo box defined!");
}
@Override
public void editingCanceled(ChangeEvent e) {
System.out.println("Edition canceled, set the old value");
}
});
这样您就可以仅在 ComboBox 定义了值时执行操作。
希望对您有所帮助。
您不应该为此使用 ActionListener。当一个项目被选中时,组合框使用它自己的 ActionListener 来更新 TableModel。
因此,您应该监听 TableModel 中的更改,以便执行您的自定义代码。所以你应该使用 TableModelListener
来监听数据的变化。但是,即使只是开始和停止编辑单元格,TableModelListener
也可以触发事件,这对您来说可能是个问题。
在这种情况下你可以使用Table Cell Listener。它只会在 TableModel 中的值发生变化时生成事件。