在Jtable单元格中单击JComboBox时调用ActionPerformed

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Jtable单元格中单击JComboBox时调用ActionPerformed相关的知识,希望对你有一定的参考价值。

我在JComboBox细胞中使用Jtable。当我点击JComboBox并从中选择一个值时,它会调用ActionPerformed函数。到这里它工作正常,但一旦我再次点击JComboBox,它会调用ActionPerformed函数,它不应该。我想要的是,当在ActionPerformed中选择项目时调用JComboBox函数。换句话说,当从JComboBox中选择项目然后调用ActionPerformed函数时,它应该工作,因为它第一次起作用。我无法弄清楚为什么会出现这个问题。以下是我查看的链接,我也进行了一些其他搜索,但仍无法找到上述问题的任何相关答案。

  1. Adding JComboBox to a JTable cell
  2. How to use ActionListener on a ComboBox to give a variable a value
  3. 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");
    }
}

请告诉我为什么会出现这个问题以及我该如何解决它。

答案

不幸的是,在使用DefaultCellEditor时你不能做太多 - 这就是它的行为方式。在您的代码中,您可以添加一个检查以确保在处理事件之前发生了值的更改。如下所示:

public void actionPerformed(ActionEvent e) {
    if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
        JOptionPane.showMessageDialog(null, "actionPerformed called: ");
    skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
另一答案

您可以尝试使用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);
    }
}
另一答案

发生这种情况是因为您使用与第2列的DefaultCellEditor相同的JComboBox。

每当您单击第2列中的单元格时,ComboBox将更改为此时单元格上的值,并触发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时调用ActionPerformed的主要内容,如果未能解决你的问题,请参考以下文章

让 JComboBox 在 JTable 中显示而不先单击它

点击Jtable 后 如何让jcombobox 值为点击Jtable的值

如何将JComboBox添加到JTable单元格?

浅析JTable与TableModelTableCellRendererTableCellEditor接口——使用JComboBox显示单元格的值

什么是JTable的任何单元格中的更改的正确事件?

怎么在JTable表格中加入如JComboBox之类的控件?有注释加分。