Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

before cell select jtable event

Tags:

java

swing

jtable

Are there any event that is fired when cell is about to be selected? There is ListSelectionListener, but it has event that is fired only after selection has happened. I need some way to cancel selection event and using ListSelectionListener it is not easy as selection has already happened and I need to have some state variable that indicates if selection is normal or is cancel of a previous selection.

Are there a way to switch off selection notifications? However this is not 100% good solution (there will be problems if some listeners saves selection state in its local storage) this is better than nothing.

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.");
            }
        }
    }

}
like image 493
michael nesterenko Avatar asked Oct 29 '11 00:10

michael nesterenko


2 Answers

whatever the goal is that you want to achieve: thinking "mouseEvent" is not enough, selection might change for other reasons (f.i. keyboard input, programmatic trigger, ..). Reverting an unwated change in a listener is not an option: as you already noted that would require to keep a duplicate of the selection and might confuse other listeners.

The only way (that I see, could be others, of course ;-) is not to let it happen in the first place: implement a List SelectionModel which doesn't change the selection if certain conditions are met. My favourite (biased me :-) is a VetoableListSelectionModel It's a subclass of DefaultListSelectionModel which in SingleSelectionMode waits for vetoes from interested parties before actually changing.

Here's a (raw) code snippet using it:

    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);
like image 148
kleopatra Avatar answered Oct 19 '22 23:10

kleopatra


The only way to do this that i can think of is handle the MouseEvent and using MouseAdapters, get the coordinates and somehow to check whether the mouse pointer is hovering over a cell or not, if it is, do what you want to do. you probably have to do addMouseListener to get the effect.

like image 1
Aman Avatar answered Oct 20 '22 00:10

Aman