ActionPerformed вызывается при нажатии JComboBox в ячейке Jtable - PullRequest
0 голосов
/ 31 августа 2018

Я использую JComboBox в Jtable ячейке. Когда я нажимаю JComboBox и выбираю из него значение, оно вызывает функцию ActionPerformed. До сих пор он работает нормально, но как только я снова нажимаю JComboBox, он вызывает функцию ActionPerformed, чего не должно быть. Я хочу вызвать функцию ActionPerformed, когда элемент выбран в JComboBox. Другими словами, он должен работать так же, как в первый раз, когда элемент был выбран из JComboBox, а затем была вызвана функция ActionPerformed. Я не могу понять, почему эта проблема возникает. Вот ссылки, на которые я смотрел, и я также провел некоторые другие поиски, но все еще не мог найти никакого относительного ответа на вышеупомянутую проблему.

  1. Добавление JComboBox в ячейку JTable
  2. Как использовать ActionListener в ComboBox для присвоения переменной значения
  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");
    }
}

Пожалуйста, скажите мне, почему эта проблема возникает и как я должен ее решить.

Ответы [ 4 ]

0 голосов
/ 31 августа 2018

Вы не должны использовать ActionListener для этого. Поле со списком использует собственный ActionListener для обновления TableModel при выборе элемента.

Так что вместо этого вы должны прислушиваться к изменениям в TableModel для того, чтобы сделать ваш собственный код. Поэтому вы должны использовать TableModelListener для прослушивания изменений в данных. Однако TableModelListener может вызвать событие, даже если просто начать и остановить редактирование ячейки, что может быть проблемой для вас.

В этом случае вы можете использовать Table Cell Listener . Он будет генерировать событие только тогда, когда значение в TableModel изменилось.

0 голосов
/ 31 августа 2018

К сожалению, вы не можете многое сделать при использовании DefaultCellEditor - так он себя ведет. В вашем коде вы можете добавить проверку, чтобы убедиться, что изменение значения произошло до обработки события. Примерно так:

public void actionPerformed(ActionEvent e) {
    if (skuNameSelected == null || skuNameComboBoxTable.getSelectedItem() != skuNameSelected)
        JOptionPane.showMessageDialog(null, "actionPerformed called: ");
    skuNameSelected = (String) skuNameComboBoxTable.getSelectedItem();
}
0 голосов
/ 31 августа 2018

Это происходит потому, что вы используете тот же JComboBox, что и DefaultCellEditor для столбца 2.

Каждый раз, когда вы щелкаете ячейку из столбца 2, ComboBox изменится на значение, которое находится на ячейке в данный момент и которое вызывает DESELECT (из старого значения) и SELECT (для нового значения). Это произойдет, только если старое значение и новое значение не совпадают .

Один из способов избежать этого - добавить CellEditorListener в используемый вами DefaultCellEditor, как показано ниже:

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.

Надеюсь, это поможет.

0 голосов
/ 31 августа 2018

Вы можете попробовать использовать 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);
    }
}
...