Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java JTable disable single cell selection border highlight

I have a JTable with three columns in each row, see the image:

enter image description here

For some reason depending on the column i select i get the little dark blue border around it (V140116554) in the image above.

I currently use this to select the entire row:

vTable.setRowSelectionAllowed(true);

How can i disable this?

EDIT:

Added a class:

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 added it:

vTable.setDefaultRenderer(String.class, new VisitorRenderer());

But still get the border

like image 392
Alosyius Avatar asked Sep 14 '13 11:09

Alosyius


People also ask

How to disable a particular cell in JTable?

By default, we can edit the text and modify it inside a JTable cell. We can also disable the cell editing inside a table by calling the editCellAt() method of JTable class and it must return false.

How to remove selection in JTable?

We can remove a selected row from a JTable using the removeRow() method of the DefaultTableModel class.

How do you make a JTable cell editable?

jTableAssignments = new javax. swing. JTable() { public boolean isCellEditable(int rowIndex, int colIndex) { return editable; }};

How do you make a JTable column not editable?

Right-click on the table cells. From popup menu, choose "Table Contents..". Uncheck the editable check box for the column you want to make it non-editable.


2 Answers

The TableCellRenderer is responsible for drawing the focus rectangle around the currently focused cell. You need to supply your own renderer that is capable of either overriding this feature or providing its own...

For example;

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 component's Border to noFocusBorder which is defined in DefaultTableCellRenderer as a EmptyBorder

You will then need to set this renderer as the default renderer for the effected columns. Check out How to use tables for more details

Update with example

Works fine for me...

enter image description here

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

enter image description here

From the looks of things, the visitor column class type isn't being reported as String by the TableModel...

Updated with proxy renderer concept

Because you want to remove the focus border from every cell. You have three choices...

  1. Write a custom cell renderer for every possibility of Class type you might need for your table. This can time consuming and repeats a lot of code to achieve only a small effect.
  2. Do nothing a live with it...
  3. Use a "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, remove 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());

Which we did before, we would do this instead...

table.setDefaultRenderer(String.class, 
    new ProxyCellRenderer(table.getDefaultRenderer(String.class)));

This means we can take advantage of the what ever default renderer is already available without knowing what that might be, but also supply our own custom requirements to it...

like image 159
MadProgrammer Avatar answered Oct 01 '22 20:10

MadProgrammer


If you have absolutely no need for the border on any cell in that table, just apply MyRenderer to all cells, regardless of class. You can do it like this:

table.setDefaultRenderer(Object.class, new MyRenderer());

like image 40
Pranx Avatar answered Oct 01 '22 22:10

Pranx