JTable: JComboBox ItemListener запущен без изменений

Я добавил JComboBox в JTable:

table.getColumnModel().getColumn(16).setCellEditor(new  DefaultCellEditor(c = new JComboBox()));
c.addItemListener(new CItemListener());

Слушатель запускается при (отмене) выбора элемента. Это нормально. Однако моя проблема заключается в том, что я говорю: у меня выбрано «B» в одном поле со списком строк и «A» в другом. Когда у меня выбрано поле со списком + строка «B», а теперь я выбираю строку с «A», прослушиватель запускается с отключенным элементом «B» и выбранным «A», хотя я не изменил выбор сам по себе. Это верно только в том случае, если я нажимаю на поле со списком (без изменения выбора), а не в том случае, если я выбираю строку где-то еще.

Можно ли изменить это поведение? Если да: как?

Цель: прослушиватель запускается только при выборе, а не при отмене/выборе поля со списком без изменения элемента.

Слушатель:

@Override
public void itemStateChanged(ItemEvent ie) {
    String s = "";

    if (ie.getStateChange() == ItemEvent.SELECTED){
        if (table.getSelectedRow() != -1){
            s = table.getModel().getValueAt(table.convertRowIndexToModel(table.getSelectedRow()), 1) );
            anotherTable.increaseCountFor(s);
            }
        } else if (ie.getStateChange() == ItemEvent.DESELECTED){
            if (table.getSelectedRow() != -1){
                s = table.getModel().getValueAt(table.convertRowIndexToModel(table.getSelectedRow()), 1) );
                anotherTable.decreaseCountFor(s);
            }
        }

person user4591830    schedule 17.07.2015    source источник
comment
прослушиватель элементов будет срабатывать для всех строк, поскольку поле со списком c будет использоваться для всех строк в этом столбце. выполните проверку в элементе прослушивания. Можете ли вы опубликовать код CItemListener или MCVE   -  person Madhan    schedule 19.07.2015
comment
Ах вот почему. Конечно, если я выберу ту же комбинацию с другим предметом, будет сделан (от) выбор. Это действительно очень полезно. Мой Listener довольно прост, я добавлю его выше.   -  person user4591830    schedule 20.07.2015
comment
какова ваша конечная цель[что вы собираетесь делать в //do something]?Проверить выбранную строку и внести изменения только в эту строку.например, dochangesinrow(table.getSelecterow())   -  person Madhan    schedule 20.07.2015
comment
См. правку выше. Я получаю значение s из модели, так как столбец 1 скрыт. Счетчик для (от)выделенного элемента (от)увеличивается в другой таблице. Этот счетчик явно ошибочен, когда слушатель запускается без изменения фактического выбора.   -  person user4591830    schedule 20.07.2015


Ответы (1)


Проблемы с вашим текущим подходом

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

Нет необходимости слушать изменение выпадающего списка, что вы хотите слушать в изменении столбца таблицы.

Поскольку вы увеличиваете на основе некоторого значения значений со списком. Я придумал следующее решение.

Существует mainTable, в котором 2-й столбец [индекс 1] является раскрывающимся списком. Всякий раз, когда значение поля со списком изменяется для любой строки в mainTable, старое значение уменьшается, а новое значение увеличивается в counterTable.

Я переопределил DefaultTableModel, так что всякий раз, когда вызывается setValue, он будет проверять, является ли это нашим желаемым столбцом, и если да, то он будет уменьшать старое значение и увеличивать новое значение в таблице счетчиков.

Просто запустите приведенный ниже код SSCCE, выберите значения из второго столбца и посмотрите изменения.

Следующее делает то, что вы просили

import java.awt.BorderLayout;
import java.util.Objects;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;


public class TableDropDown extends JFrame {

private JComboBox jComboBox1;
private JTable mainTable = new JTable();
private JTable counterTable = new JTable();

public TableDropDown() {
    initialize();
}

private void initialize() {

    //Loading the mainTable with sample values 
    DefaultTableModel model = new DefaultTableModel(new Object[][]{
        {"Test", null, null},
        {"Type", null, null},
        {"What", null, null},
        {"Which", null, null}
    },
            new String[]{
                "Title 1", "Title 2", "Title 3"
            }) {
                @Override
                //Main part that does the trick
                public void setValueAt(Object newValue, int row, int column) {
                    //check if this is our column
                    if (column == 1) {
                        Object oldvalue = getValueAt(row, column);
                        if (!Objects.equals(newValue, oldvalue)) {
                            if (oldvalue != null) {
                                decreaseCountFor(oldvalue.toString());
                            }
                            increaseCountFor(newValue.toString());
                        }
                    }
                    super.setValueAt(newValue, row, column);
                }
            };

    mainTable.setModel(model);

    //loading counterTable and combobox sample values A to J
    String[] contents = new String[10];
    DefaultTableModel cModel = new DefaultTableModel(null,
            new String[]{"Type", "Count"});
    for (int i = 0; i < 10; i++) {
        contents[i] = "" + (char) (i + 65);
        cModel.addRow(new Object[]{contents[i], 0});
    }
    counterTable.setModel(cModel);
    counterTable.setEnabled(false);//to disable editing

    jComboBox1 = new JComboBox(new DefaultComboBoxModel(contents));

    //setting cellEditor for Column 1
    mainTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jComboBox1));

    //stuffs to add value to frame
    add(new javax.swing.JScrollPane(mainTable), BorderLayout.CENTER);
    add(new javax.swing.JScrollPane(counterTable), BorderLayout.EAST);
    pack();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public int getRowForValue(String val) {
    for (int i = 0; i < counterTable.getRowCount(); i++) {
        if (counterTable.getValueAt(i, 0).equals(val)) {
            return i;
        }
    }
    return -1;
}

public int getPrevoiusValue(int row) {
    return Integer.parseInt(counterTable.getValueAt(row, 1).toString());
}

public void increaseCountFor(String x) {
    int row = getRowForValue(x);
    counterTable.setValueAt(getPrevoiusValue(row) + 1, row, 1);
}

public void decreaseCountFor(String x) {
    int row = getRowForValue(x);
    counterTable.setValueAt(getPrevoiusValue(row) - 1, row, 1);
}

public static void main(String[] args) {
    new TableDropDown().setVisible(true);
}
}
person Madhan    schedule 20.07.2015
comment
Большое спасибо! Переопределение setValue моделей с добавлением проверки делает свое дело. И не только это: это намного чище и короче, чем с Listener, так как Listener вообще не нужен. - person user4591830; 20.07.2015