【问题标题】:ActionPerformed being called when JComboBox is clicked in Jtable cell在 Jtable 单元格中单击 JComboBox 时调用 ActionPerformed
【发布时间】:2018-08-31 13:19:59
【问题描述】:

我在Jtable 单元格中使用JComboBox。当我单击JComboBox 并从中选择一个值时,它会调用ActionPerformed 函数。到这里它工作正常,但只要我再次单击JComboBox,它就会调用ActionPerformed 函数,它不应该这样做。我想要的是,在JComboBox 中选择项目时调用ActionPerformed 函数。换句话说,它应该像第一次从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");
    }
}

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

【问题讨论】:

    标签: java swing jframe jtable


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        发生这种情况是因为您使用与第 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 定义了值时执行操作。

        我希望这会有所帮助。

        【讨论】:

          【解决方案4】:

          您不应该为此使用 ActionListener。选择项目时,组合框使用自己的 ActionListener 来更新 TableModel。

          因此,您应该监听 TableModel 中的更改,以便执行您的自定义代码。所以你应该使用TableModelListener 来监听数据的变化。但是,TableModelListener 可以触发事件,即使只是开始和停止编辑单元格,这对您来说可能是个问题。

          在这种情况下,您可以使用Table Cell Listener。只有当 TableModel 中的值发生变化时才会产生事件。

          【讨论】:

            猜你喜欢
            • 2020-01-02
            • 2011-03-16
            • 1970-01-01
            • 2015-03-07
            • 1970-01-01
            • 2012-03-05
            • 1970-01-01
            • 2021-06-20
            • 2016-06-10
            相关资源
            最近更新 更多