TableCellRenderer
is responsible for drawing a focus rectangle around the current focused cell. You need to provide your own render, capable of either overriding this function, or providing your own ...
For instance;
public class MyRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); setBorder(noFocusBorder); return this; } }
This uses the DefaultTableCellRenderer
as the base renderer and sets the Border
component to noFocusBorder
which is defined in the DefaultTableCellRenderer
as EmptyBorder
Then you will need to install this renderer as the default renderer for the involved columns. Check how to use tables for more details.
Refresh with example
It works fine for me ...
import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.LineBorder; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; public class TableRenderer { public static void main(String[] args) { new TableRenderer(); } public TableRenderer() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } DefaultTableModel model = new DefaultTableModel(new Object[][]{{"", "One"}, {"", "Two"}}, new Object[]{"Check", "Vistor"}) { @Override public Class<?> getColumnClass(int columnIndex) { return String.class; } }; JTable table = new JTable(model); table.setRowSelectionAllowed(true); table.setShowGrid(false); table.setDefaultRenderer(String.class, new VisitorRenderer()); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(table)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class VisitorRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); setBorder(noFocusBorder); return this; } } }
And just to be sure, I changed setBorder(noFocusBorder);
to ...
if (hasFocus) { setBorder(new LineBorder(Color.RED)); }
TableModel
throughout, the visitor column class type is not TableModel
like String
in TableModel
...
Updated with proxy rendering concept
Because you want to remove the focus border from each cell. You have three options ...
- Write a custom cell renderer for each
Class
feature you may need for your table. This can take a lot of time and repeat the code many times to achieve only a small effect. - Do nothing to live with it ...
- Use the "proxy" renderer. This is a renderer that uses another
TableCellRenderer
to perform the actual rendering process, but applies some minor changes to the result, for example, removing the border ...
...
public static class ProxyCellRenderer implements TableCellRenderer { protected static final Border DEFAULT_BORDER = new EmptyBorder(1, 1, 1, 1); private TableCellRenderer renderer; public ProxyCellRenderer(TableCellRenderer renderer) { this.renderer = renderer; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component comp = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (comp instanceof JComponent) { ((JComponent)comp).setBorder(DEFAULT_BORDER); } return comp; } }
Instead of doing something like ...
table.setDefaultRenderer(String.class, new VisitorRenderer());
What we did before, we would do it instead ...
table.setDefaultRenderer(String.class, new ProxyCellRenderer(table.getDefaultRenderer(String.class)));
This means that we can take advantage of the default rendering tool, not knowing what it can be, but also providing our own requirements for it ...