在细胞选择jtable事件之前

当要选择单元格时是否会触发任何事件? 有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."); } } } } 

无论你想达到什么目标:认为“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); 

我能想到的唯一方法是处理MouseEvent并使用MouseAdapters ,获取坐标并以某种方式检查鼠标指针是否hover在单元格上,如果是,请执行您想要执行的操作。 你可能需要做addMouseListener来获得效果。

假设您已将ListSelectionModel的选择模式设置为所需的值并添加了一个侦听器,您可能会发现检查谓词getValueIsAdjusting()很有帮助,“如果选择正在进行一系列更改,则返回true ”。 实际上,当鼠标按下时,或者在其中一个INTERVAL模式下拖动鼠标时,都是true

它可能也有助于更多地了解这项工作的目标,因为另一种方法可能会有所帮助。 当然, 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() ,如本例所示。