Question

I have following code:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableModel;

public class NewClass1 extends JFrame {
    private JTable table;
    private JScrollPane scrollPane;
    private DefaultTableModel defaultTableModel;

    public NewClass1() {
        setLocationByPlatform(true);
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(600, 400));
        setTitle("Table Issues");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        createTableModel();
        table = new JTable(defaultTableModel);

        scrollPane = new JScrollPane(table);

        getContentPane().add(scrollPane, BorderLayout.CENTER);

        pack();
    }

    private void createTableModel() {
        Vector cols = new Vector();
        cols.add("A");

        Vector rows = new Vector();
        for (int i = 0; i < 50; i++) {
            Vector row = new Vector();
            row.add((i + 1) + "");
            rows.add(row);
        }

        defaultTableModel = new DefaultTableModel(rows, cols) {
            Class[] types = new Class[]{
                String.class
            };

            @Override
            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(new NimbusLookAndFeel());
        } catch (Exception e) {
        }

        final NewClass1 nc = new NewClass1();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                nc.setVisible(true);
            }
        });

        while (true) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    int row = (int) (Math.random() * 50);
                    int move = (int) (Math.random() * 50);

                    nc.defaultTableModel.moveRow(row, row, move);
                }
            });
            try{
                Thread.sleep(1000);
            }catch(Exception e){
            }
        }
    }
}

Please run the above code and select row.

My problem is with row movement, row selection is not moving. It is staying at fixed position. Suppose I selected row with column value 25, selected row must be of column value 25 after row movements.

Please help me on this.

My real problem is, user will select row and clicks menu to perform action, meanwhile other threads may have moved rows, and performed action will be on other row than actual one.

Was it helpful?

Solution

The easiest way is to remember the selected row somewhere outside of the ListSelectionModel and adjust the selection whenever the TableModel changes. For example you could do this:

public class NewClass1 extends JFrame {
    private JTable table;
    private DefaultTableModel defaultTableModel;
    private JScrollPane scrollPane;

    private class SelectionHelper implements ListSelectionListener, TableModelListener {
        private Object selectedRow;

        @Override
        public void valueChanged(ListSelectionEvent event) {
            if (!event.getValueIsAdjusting()) return;
            int selectedIndex = table.getSelectedRow();
            if (selectedIndex >= 0) {
                selectedRow = defaultTableModel.getDataVector().get(selectedIndex);
            } else {
                selectedRow = null;
            }
        }

        @Override
        public void tableChanged(TableModelEvent event) {
            if (selectedRow == null) return;
            int selectedIndex = defaultTableModel.getDataVector().indexOf(selectedRow);
            table.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
        }
    }

    public NewClass1() {
        // ...
        createTableModel();
        table = new JTable(defaultTableModel);

        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        SelectionHelper helper = new SelectionHelper();
        table.getModel().addTableModelListener(helper);
        table.getSelectionModel().addListSelectionListener(helper);
        // ...
    }
    // ...
}

Note however, that you should adjust this code for production use, for example in regards to thread safety or portability (using the table and defaultTableModel attributes in the inner class is bad style).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top