перед ячейкой выберите jtable событие - PullRequest
6 голосов
/ 29 октября 2011

Есть ли какое-либо событие, которое запускается, когда ячейка собирается быть выбранной? Существует ListSelectionListener, но у него есть событие, которое запускается только после того, как выбор произошел. Мне нужен какой-то способ отменить событие выбора, и с помощью ListSelectionListener это нелегко, так как выбор уже произошел, и мне нужна переменная состояния, которая указывает, является ли выбор нормальным или отменяет предыдущий выбор.

Есть ли способ отключить уведомления о выборе? Однако это не на 100% хорошее решение (будут проблемы, если некоторые слушатели сохранят состояние выбора в локальном хранилище), это лучше, чем ничего.

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.JTable;

public class JTableExample extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 6040280633406589974L;
    private JPanel contentPane;
    private JTable table;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    JTableExample frame = new JTableExample();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public JTableExample() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        table = new JTable(new MyTableModel());
        ListSelectionModel selectionModel = table.getSelectionModel();
        selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        selectionModel.addListSelectionListener(new MySelectionListener());
        contentPane.add(table, BorderLayout.CENTER);
    }

    class MyTableModel extends AbstractTableModel {
        /**
         * 
         */
        private static final long serialVersionUID = -8312320171325776638L;

        public int getRowCount() {
            return 10;
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return rowIndex * columnIndex;
        }
    }

    class MySelectionListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent e) {
            int selectedRow = table.getSelectedRow();
            if (selectedRow == 5) {
                System.out.println("I would like this selection never happened.");
            }
        }
    }

}

Ответы [ 3 ]

6 голосов
/ 29 октября 2011

Независимо от цели, которую вы хотите достичь: мышления «mouseEvent» недостаточно, выбор может измениться по другим причинам (ввод с клавиатуры, программный триггер, ...).Отмена ненатронутого изменения в слушателе не вариант: как вы уже отметили, это потребует сохранения дубликата выбора и может запутать других слушателей.

Единственным способом (который я вижу, могут быть другие,конечно ;-) это , чтобы не допустить этого в первую очередь: реализовать List SelectionModel, которая не меняет выбор, если выполняются определенные условия.Мой любимый (пристрастный меня :-) это VetoableListSelectionModel Это подкласс DefaultListSelectionModel, который в SingleSelectionMode ждет вето от заинтересованных сторон, прежде чем фактически измениться.

Вот (необработанный) фрагмент кода с его использованием:

    VetoableListSelectionModel vetoableSelection = new VetoableListSelectionModel();
    VetoableChangeListener navigationController = new VetoableChangeListener() {

        public void vetoableChange(PropertyChangeEvent evt)
                throws PropertyVetoException {
            // custom method that implements your condition 
            if (!canSelect((int) evt.getOldValue(), (int) evt.getNewValue()))
                throw new PropertyVetoException("uncommitted changes",
                        evt);
        }

    };
    vetoableSelection.addVetoableChangeListener(navigationController);
    myTable.setSelectionModel(vetoableSelection);
1 голос
/ 29 октября 2011

Предполагая, что вы установили режим выбора ListSelectionModel на желаемое значение и добавили слушателя, вам может быть полезно проверить предикат getValueIsAdjusting(), «Возвращает true, если выбор подвергается серии изменений.» На практике это true, когда мышь не работает или когда ее перетаскивают в одном из режимов INTERVAL.

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

Добавление: похоже, это работает, но подход @ kleopatra предотвратит потерю предыдущего выбора.

private static final int FORBID = 5;
class MySelectionListener implements ListSelectionListener {

    public void valueChanged(ListSelectionEvent e) {
        int selectedRow = table.getSelectedRow();
        if (selectedRow == FORBID) {
            selectionModel.removeIndexInterval(FORBID, FORBID);
            System.out.println(FORBID + " forbidden.");
        }
    }
}

Пользователю запрещается изменять строку, если он не принял изменения, внесенные в эту строку.

Вы можете использовать пользовательские CellEditor, которые обуславливают stopCellEditing(), как показано в этом примере .

1 голос
/ 29 октября 2011

Единственный способ сделать это, о котором я могу думать, это обработать MouseEvent и, используя MouseAdapters, получить координаты и каким-то образом проверить, находится ли указатель мыши над ячейкой или нет, если это так, выполните что ты хочешь делать. вам, вероятно, придется сделать addMouseListener, чтобы получить эффект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...