Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTable disable Column Selection

Tags:

java

swing

jtable

enter image description here

I am trying to disable selection of rows in all but 1 column in a JTable. (Layer Column in the example screenshot). In the other columns I have spinners and checkboxes that I want the user to be able to interact with, without effecting the selections in the Layer Column.

My initial attempt was to store up any selected rows as they occur, and then revert to that set of selected rows when a cell outside of column A is selected. It sort of works, but the problem is that it "flashes" when the other cell is selected, before it reverts it back. How can I prevent the "flash"?

Here is an example I set up to illustrate the problem:

public class TableTest {

    static int[] selectedRows = new int[0];

    final static String[] columns = new String[] { "Layer", "Enabled", "Read Only", "Storage" };

    final static DefaultTableModel model = new DefaultTableModel(new Vector(), new Vector(Arrays.asList(columns))) {

        @Override
        public void setValueAt(Object obj, int row, int col) {

            if (obj instanceof Boolean || obj instanceof Integer) {
                Object localObject = super.getValueAt(row, col);
                if (localObject instanceof Integer) {

                    Integer val = (Integer) localObject;

                    ((SpinnerCell) obj).getSpinner().setValue(val);
                } else if (localObject instanceof Boolean) {

                    Boolean val = (Boolean) localObject;

                    ((CheckboxCell) obj).getCheckBox().setEnabled(val);
                }

            } else {
                super.setValueAt(obj, row, col);
            }

        }

        @Override
        public boolean isCellEditable(int rowIndex, int colIndex) {

            return colIndex != 0;
        }

    };

    public static void main(String[] a) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final JTable table = new JTable(model) {

                    @Override
                    public TableCellRenderer getCellRenderer(final int rowIndex, int colIndex) {

                        int reaRowlIndex = convertRowIndexToModel(rowIndex);
                        int realColumnIndex = convertColumnIndexToModel(colIndex);

                        Object o = model.getValueAt(reaRowlIndex, realColumnIndex);

                        if (o instanceof TableCellRenderer) {
                            return (TableCellRenderer) o;
                        } else {
                            return super.getCellRenderer(reaRowlIndex, realColumnIndex);
                        }
                    }

                    //
                    @Override
                    public TableCellEditor getCellEditor(final int rowIndex, int colIndex) {

                        int reaRowlIndex = convertRowIndexToModel(rowIndex);
                        int realColumnIndex = convertColumnIndexToModel(colIndex);

                        Object o = model.getValueAt(reaRowlIndex, realColumnIndex);

                        if (o instanceof TableCellEditor) {
                            return (TableCellEditor) o;
                        } else {
                            return super.getCellEditor(reaRowlIndex, realColumnIndex);
                        }
                    }

                };

                table.getTableHeader().setReorderingAllowed(false);

                table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

                    @Override
                    public void valueChanged(ListSelectionEvent arg0) {
                        if (table.getSelectedColumn() == 0) {
                            selectedRows = table.getSelectedRows();

                            System.out.println("Selected Rows before " + Arrays.toString(selectedRows));
                        }

                    }
                });

                final ListSelectionModel columnListSelectionModel = table.getColumnModel().getSelectionModel();
                columnListSelectionModel.addListSelectionListener(new ListSelectionListener() {
                    @Override
                    public void valueChanged(ListSelectionEvent e) {

                        if (table.getSelectedColumn() != 0) {

                            table.clearSelection();

                            System.out.println("Selected Rows during " + Arrays.toString(table.getSelectedRows()));

                            for (int i = 0; i < selectedRows.length; i++) {
                                table.getSelectionModel().addSelectionInterval(selectedRows[i], selectedRows[i]);
                            }

                            System.out.println("Selected Rows after " + Arrays.toString(table.getSelectedRows()));
                        }

                    }
                });

                model.addRow(new Object[] { "Bird", new CheckboxCell(new JCheckBox()),
                        new CheckboxCell(new JCheckBox()), new SpinnerCell(new JSpinner()) });

                model.addRow(new Object[] { "Cat", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
                        new SpinnerCell(new JSpinner()) });

                model.addRow(new Object[] { "Dog", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
                        new SpinnerCell(new JSpinner()) });

                model.addRow(new Object[] { "Fish", new CheckboxCell(new JCheckBox()),
                        new CheckboxCell(new JCheckBox()), new SpinnerCell(new JSpinner()) });

                model.addRow(new Object[] { "Pig", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
                        new SpinnerCell(new JSpinner()) });

                frame.add(new JScrollPane(table));

                frame.setSize(300, 200);
                frame.setVisible(true);

            }

        });

    }

    static class CheckboxCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

        private static final long serialVersionUID = 1L;
        private JCheckBox checkBox;

        public CheckboxCell(JCheckBox inputCheckBox) {
            checkBox = inputCheckBox;
        }

        @Override
        public Object getCellEditorValue() {
            return checkBox.isSelected();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
                int column) {

            return checkBox;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {

            return checkBox;
        }

        public JCheckBox getCheckBox() {
            return checkBox;
        }

        @Override
        public boolean isCellEditable(EventObject evt) {
            return true;
        }

        public String toString() {
            return checkBox.isSelected() + "";
        }

    }

    static class SpinnerCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

        private static final long serialVersionUID = 1L;
        private JSpinner editSpinner, renderSpinner;

        public SpinnerCell() {
            editSpinner = new JSpinner();
            JTextField tf = ((JSpinner.DefaultEditor) editSpinner.getEditor()).getTextField();
            tf.setForeground(Color.black);
            renderSpinner = new JSpinner();
            JTextField tf2 = ((JSpinner.DefaultEditor) renderSpinner.getEditor()).getTextField();
            tf2.setForeground(Color.black);
        }

        public SpinnerCell(JSpinner showSpinner) {
            editSpinner = showSpinner;
            JTextField tf = ((JSpinner.DefaultEditor) editSpinner.getEditor()).getTextField();
            tf.setForeground(Color.black);
            renderSpinner = showSpinner;
            JTextField tf2 = ((JSpinner.DefaultEditor) renderSpinner.getEditor()).getTextField();
            tf2.setForeground(Color.black);

        }

        @Override
        public Object getCellEditorValue() {
            return editSpinner.getValue();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
                int column) {

            return editSpinner;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            return renderSpinner;
        }

        public String toString() {
            return editSpinner.getValue().toString();
        }

        public JSpinner getSpinner() {
            return editSpinner;
        }

        @Override
        public boolean isCellEditable(EventObject evt) {
            return true;
        }
    }

}
like image 314
mainstringargs Avatar asked Jun 07 '16 21:06

mainstringargs


People also ask

How do I disable a specific cell in JTable?

We can also disable the cell editing inside a table by calling the editCellAt() method of JTable class and it must return false.

How do you disable a column in Java?

JTable table = new JTable() { @Override public boolean isCellEditable(int row, int column) { return false; }; }; You might want to override the method isCellEditable to selectively disable a particular column, like return (column == 0) would disable the first column. Don't forget that the first column is column 0 .


1 Answers

Here's my short example:

  • Override JTable#changeSelection(...)
  • table.setCellSelectionEnabled(true);
  • Override ListSelectionModel#isSelectedIndex(...)
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class TableTest2 {
  public JComponent makeUI() {
    String[] columnNames = {"Layer", "Enabled", "Read Only"};
    Object[][] data = {
      {"Bird", true, false}, {"Cat",  true, false},
      {"Dog",  true, false}, {"Fish", true, false}, {"Pig",  true, false}
    };
    TableModel model = new DefaultTableModel(data, columnNames) {
      @Override public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
      }
      @Override public boolean isCellEditable(int row, int col) {
        return col != 0;
      }
    };
    JTable table = new JTable(model) {
      @Override public void changeSelection(
          int rowIndex, int columnIndex, boolean toggle, boolean extend) {
        if (convertColumnIndexToModel(columnIndex) != 0) {
          return;
        }
        super.changeSelection(rowIndex, columnIndex, toggle, extend);
      }
    };
    table.setAutoCreateRowSorter(true);
    table.setCellSelectionEnabled(true);
    table.getColumnModel().setSelectionModel(new DefaultListSelectionModel() {
      @Override public boolean isSelectedIndex(int index) {
        return table.convertColumnIndexToModel(index) == 0;
      }
    });
    return new JScrollPane(table);
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TableTest2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}
like image 51
aterai Avatar answered Oct 16 '22 23:10

aterai