Java JTable 禁用单单元格选择边框高亮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18801137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:12:03  来源:igfitidea点击:

Java JTable disable single cell selection border highlight

javaswingjtablebordertablecellrenderer

提问by Alosyius

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

我有一个每行三列的 JTable,请参见图像:

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.

出于某种原因,根据我选择的列,我在上图中得到了它周围的深蓝色小边框 (V140116554)。

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

但仍然得到边界

采纳答案by MadProgrammer

The TableCellRendereris 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...

TableCellRenderer负责绘制焦点矩形当前重点细胞周围。您需要提供自己的渲染器,该渲染器能够覆盖此功能或提供自己的...

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 DefaultTableCellRendereras the base renderer and sets the component's Borderto noFocusBorderwhich is defined in DefaultTableCellRendereras a EmptyBorder

这将使用DefaultTableCellRenderer作为基础渲染器和设置组件的BordernoFocusBorder其在定义DefaultTableCellRenderer为一个EmptyBorder

You will then need to set this renderer as the default renderer for the effected columns. Check out How to use tablesfor 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...

可以肯定的是,我改为setBorder(noFocusBorder);...

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 Stringby the TableModel...

从事物的外表,访问者列类类型没有被报告为StringTableModel...

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 Classtype 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 TableCellRendererto perform the actual rendering process, but applies some minor changes to the result, for example, remove the border...
  1. Class为表格可能需要的每种类型编写自定义单元格渲染器。这可能会很耗时,并且会重复很多代码来实现很小的效果。
  2. 什么都不做...
  3. 使用“代理”渲染器。这是一个渲染器,它使用另一个TableCellRenderer来执行实际的渲染过程,但会对结果进行一些细微的更改,例如,移除边框...

...

...

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...

这意味着我们可以在不知道可能是什么的情况下利用已经可用的默认渲染器,但也可以为其提供我们自己的自定义要求......

回答by Pranx

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

如果您完全不需要该表格中任何单元格的边框,只需应用于MyRenderer所有单元格,而不管类。你可以这样做:

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

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