【问题标题】:Java JTable disable single cell selection border highlightJava JTable禁用单个单元格选择边框突出显示
【发布时间】:2013-09-19 00:23:27
【问题描述】:

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

由于某种原因,取决于我选择的列,我在上面的图片中得到了它周围的小深蓝色边框(V140116554)。

我目前使用它来选择整行:

vTable.setRowSelectionAllowed(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;
    }
} 

并添加:

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

但还是得到了边框

【问题讨论】:

    标签: java swing jtable border tablecellrenderer


    【解决方案1】:

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

    例如;

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

    这使用DefaultTableCellRenderer 作为基础渲染器并将组件的Border 设置为noFocusBorderDefaultTableCellRenderer 中定义为EmptyBorder

    然后,您需要将此渲染器设置为受影响列的默认渲染器。查看How to use tables了解更多详情

    更新示例

    对我来说很好......

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

    为了确定,我将setBorder(noFocusBorder); 更改为...

    if (hasFocus) {
        setBorder(new LineBorder(Color.RED));
    }
    

    从表面上看,访问者列类类型没有被TableModel 报告为String...

    更新了代理渲染器概念

    因为您想从每个单元格中删除焦点边框。你有三个选择...

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

    而不是做类似...的事情

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

    我们以前做的,现在我们会这样做......

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

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

    【讨论】:

    • 对我来说很好用。查看更新。我怀疑您的TableModel 没有将访问者列报告为String.class...
    • 这就是问题所在,但是我有 2 列是 Icon.class 现在中间列不显示边框,但第一列和最后一列仍然存在,因为它们是 Icon.Class
    • 您必须对每种类型执行相同的操作。一个偷偷摸摸的方法是创建一个ProxyCellRenderer,它采用另一个TableCellRenderer,用它作为渲染给定单元格内容的机制,但将边框设置为EmptyBorder,这样你就可以获得默认渲染器正在使用并通过此代理渲染器提供它们...
    • 不太确定我是否关注:/
    • 抱歉,太晚了,我正要去睡觉,所以它可能是胡言乱语。查看更新
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      除了创建自己的 TableCellRenderer,您还可以这样做:

      @Override
      public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
          Component c = super.prepareRenderer(renderer, row, col);
              
          if (c instanceof JComponent)
                ((JComponent)c).setBorder(new EmptyBorder(1, 1, 1, 1));
          return c;
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2013-11-07
        • 1970-01-01
        • 1970-01-01
        • 2015-11-24
        • 2023-03-26
        相关资源
        最近更新 更多