JTable禁用列选择

时间:2016-06-07 21:51:34

标签: java swing jtable

enter image description here

我正在尝试禁用JTable中除1列之外的所有行的选择。 (示例屏幕截图中的Layer Column)。在其他列中,我有旋转器和复选框,我希望用户能够与之交互,而不会影响图层列中的选择。

我最初的尝试是在发生任何选定行时将其存储起来,然后在选择A列外的单元格时恢复到该组选定行。它有点工作,但问题是它闪现"选择其他单元格时,在将其还原之前。如何防止" flash"?

以下是我设置的示例来说明问题:

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;
        }
    }

}

3 个答案:

答案 0 :(得分:3)

如果你想要阻止闪光灯,你需要在选择之前拦截一个事件,因为table.getSelectedColumn()仅在选择完成后才有效,你总会看到该选择闪烁。

您可以使用键侦听器检查“右箭头”,“数字键盘右”和“结束”键按下以及鼠标单击的侦听器以检查用户单击的位置,然后将事件更改为选择列A仅

例如,请参阅此答案,了解如何在选择之前检查用户点击鼠标的位置:https://stackoverflow.com/a/7351053/1270000

然后,您只需添加一些代码来选择A列中的正确单元格,并且不要忘记使用事件“e.consume()”以防止原始事件因错误的用户选择而完成。

答案 1 :(得分:3)

没有尝试过,但您可以使用自定义ListSelectionModel。

以下示例允许您打开/关闭行的选择:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ToggleListSelectionModel extends DefaultListSelectionModel
{
    @Override
    public void setSelectionInterval(int index0, int index1)
    {
        //  Select multiple lines

        if (index0 != index1)
        {
            super.addSelectionInterval(index0, index1);
            return;
        }

        //  Toggle selection of a single line

        if  (super.isSelectedIndex(index0))
        {
            super.removeSelectionInterval(index0, index0);
        }
        else
        {
            super.addSelectionInterval(index0, index0);
        }
    }

    private static void createAndShowGUI()
    {
        String[] numbers = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
        final JList<String> list = new JList<String>( numbers );
        list.setVisibleRowCount( numbers.length );
        list.setSelectionModel(new ToggleListSelectionModel());
//      list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

        JButton clear = new JButton("Clear");
        clear.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                list.clearSelection();
            }
        });

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(list), BorderLayout.CENTER);
        frame.add(clear, BorderLayout.PAGE_END);
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

在您的情况下,我猜您需要访问该表,以便您可以使用getSelectedColumn()方法。

您将从上面的示例中删除逻辑并将其替换为:

if (table.getSelectedColumn() == 0)
    super.setSelectionInterval(index0, index1);

答案 2 :(得分:3)

这是我的简短例子:

  • 覆盖<?php define ("DB_ACCESS", "mysqli"); define ("DB_HOST", "***.**.*.**"); define ("DB_NAME", "test1"); define ("DB_USER", "****"); define ("DB_PASSWORD", "****"); define ("DB_PORT", "3307"); global $dbdtk_dbaccess, $dbdtk_dbhost, $dbdtk_dbuser, $dbdtk_dbpasswd, $dbdtk_dbname, $dbdtk_dbport; $dbdtk_dbaccess = DB_ACCESS; $dbdtk_dbhost = DB_HOST; $dbdtk_dbuser = DB_USER; $dbdtk_dbpasswd = DB_PASSWORD; $dbdtk_dbname = DB_NAME; $dbdtk_dbport = DB_PORT; $db = &ADONewConnection($dbdtk_dbaccess); $db->debug = 0; $db->Connect($dbdtk_dbhost, $dbdtk_dbuser, $dbdtk_dbpasswd, $dbdtk_dbname, dbdtk_dbport); $ADODB_FETCH_MODE = ADODB_FETCH_BOTH; ?>
  • JTable#changeSelection(...)
  • 覆盖table.setCellSelectionEnabled(true);
ListSelectionModel#isSelectedIndex(...)