AndroidX
AndroidX

Reputation: 648

JTable focus on entire row instead of cell

Is there any way to force a JTable to focus on entire rows instead of individual cells? I'm not talking about the row selection highlight, only about the focus border which I'd like to include all cells on the focused row.

UPDATE:

Table with non-editable cells and delete-row-functionality:

public class TableTest {

    private static void createAndShowGUI() {

        int rows = 20;
        int cols = 2;
        String[] headers = { "Column 1", "Column 2" };
        String[][] data = new String[rows][cols];

        for (int j = 0; j < rows; j++)
            for (int k = 0; k < cols; k++)
                data[j][k] = "item " + (j * cols + k + 1);

        JTable table = new JTable();

        DefaultTableModel tableModel = new DefaultTableModel(data, headers) {
            // Disable editing of the cells
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        table.setModel(tableModel);
        table.setShowGrid(false);
        table.setIntercellSpacing(new Dimension(0,0));

        // key binding to remove rows
        InputMap inputMap = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        ActionMap actionMap = table.getActionMap();
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "REMOVE");
        actionMap.put("REMOVE", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int[] rows = table.getSelectedRows();     
                for (int i = rows.length - 1; i >= 0; i--) {
                    tableModel.removeRow(rows[i]);
                }
            }
        });

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new JScrollPane(table));
        f.setSize(500, 500);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {}
                createAndShowGUI();
            }
        });
    }
}

"Focus border" on selected row:

enter image description here

"Focus border" with no rows selected:

enter image description here

"Focus border" in Windows LAF:

enter image description here

I want this "focus border" to include all cells of the row (when visible).

Below is the same code but I've added part of @camickr 's code:

public class TableTest {

    private static void createAndShowGUI() {

        int rows = 20;
        int cols = 2;
        String[] headers = { "Column 1", "Column 2" };
        String[][] data = new String[rows][cols];

        for (int j = 0; j < rows; j++)
            for (int k = 0; k < cols; k++)
                data[j][k] = "item " + (j * cols + k + 1);


        // ADDED CODE
        JTable table = new JTable() {

            private Border outside = new MatteBorder(1, 0, 1, 0, Color.BLACK);
            private Border inside = new EmptyBorder(0, 1, 0, 1);
            private Border border = new CompoundBorder(outside, inside);

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                JComponent jc = (JComponent) c;
                // Add a border to the selected row
                if (isRowSelected(row)) jc.setBorder(border);
                return c;
            }
        };


        DefaultTableModel tableModel = new DefaultTableModel(data, headers) {
            // Disable editing of the cells
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        table.setModel(tableModel);
        table.setShowGrid(false);
        table.setIntercellSpacing(new Dimension(0,0));

        // key binding to remove rows
        InputMap inputMap = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        ActionMap actionMap = table.getActionMap();
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "REMOVE");
        actionMap.put("REMOVE", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int[] rows = table.getSelectedRows();     
                for (int i = rows.length - 1; i >= 0; i--) {
                    tableModel.removeRow(rows[i]);
                }
            }
        });

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new JScrollPane(table));
        f.setSize(500, 500);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {}
                createAndShowGUI();
            }
        });
    }
}

This adds a border around the entire row (but with no left/right inset to include all cells). This is not the "focus border/rectangle", it is a border that appears around selected row only. When I delete a row the selected row is cleared and the focus border reappears.

Note that I do not want to hide the focus border (I know how to do it), I want to keep it functioning like that but to include all cells of the row instead of one cell when it becomes visible.

Upvotes: 1

Views: 1452

Answers (1)

camickr
camickr

Reputation: 324118

I just want to display FocusBorder around the entire row.

Take a look at Table Row Rendering.

It shows one way to put a Border on the row instead of individual cells.

Upvotes: 3

Related Questions