【问题标题】:background of multiline cell in JTableJTable中多行单元格的背景
【发布时间】:2023-12-23 14:19:01
【问题描述】:

我用多行单元格制作了一个表格,它工作正常,但我想在制作特定列多行单元格后更改单行的颜色,而不是整个列的颜色。我该怎么做?

这是制作第 2 列多行单元格后的图像,但整个列变成白色

这就是我所做的:

jTable1.getColumnModel().getColumn(1).setCellRenderer( new TextAreaRenderer2()); 

String test = "sunday \n monday ";

jTable1.getModel().setValueAt(test, 0, 3);
jTable1.getModel().setValueAt(test, 0, 1);
jTable1.getModel().setValueAt(test, 0, 2);

这是 TextAreaRenderer2 类:

public class TextAreaRenderer2 extends JTextArea
     implements TableCellRenderer {

     public TextAreaRenderer2() {

         Font font = new Font("Aparajita", Font.BOLD + Font.ITALIC, 16);

         setLineWrap(true);
         setWrapStyleWord(true);
         setBackground(Color.yellow);
         setBorder(BorderFactory.createEmptyBorder());
         setFont(font);

     } 

     @Override
     public Component getTableCellRendererComponent(JTable jTable,
          Object obj, boolean isSelected, boolean hasFocus, int row,
          int column) {

         setText((String)obj);
         setBackground(Color.WHITE);


         return this;
     }
 }

【问题讨论】:

    标签: java swing jtable nimbus


    【解决方案1】:

    在您的TableAreaRenderer2 类中,在getTableCellRendererComponent 方法中,您应该根据行设置背景颜色。像这样的:

    if (row % 6 < 3) {
      setBackground(Color.LIGHT_GRAY);
    } else {
      setBackground(Color.WHITE);
    }
    

    上面的代码将使3行浅灰色变成接下来的3行白色,并重复相同的图案。

    【讨论】:

    • 好的,我会这样做的。还有一件事,我怎样才能使单元格中心的文本对齐???
    • 返回的组件必须是一个JLabel,你需要将文本对齐到。
    【解决方案2】:

    事实证明这是那些问题之一:

    • 认为这是一个很好的问题,可以演示如何在自定义渲染器中获得正确的与状态相关的视觉属性
    • 实现和测试一个快速示例
    • 没有按预期工作
    • 开始调试会话

    ...几个小时后...被某些 Nimbus 的特殊性所厌恶。

    从正确的事情开始:在您的自定义渲染器(任何类型)中,引用表格的默认渲染器并使用默认属性配置自定义渲染组件。这样,您将自定义渲染组件看起来与默认组件(选择、条带化、焦点...)相同,除了您希望显式不同的状态

    public static class TextAreaRenderer2 extends JTextArea implements
            TableCellRenderer {
    
        private TableCellRenderer delegate;
    
        public TextAreaRenderer2(TableCellRenderer delegate) {
            this.delegate = delegate;
            // initial config
            Font font = new Font("Aparajita", Font.BOLD + Font.ITALIC, 16);
            setFont(font);
            setLineWrap(true);
            setWrapStyleWord(true);
        }
    
        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            // configure content
            setText((String) value);
            // get a configured component from the delegate
            Component comp = delegate.getTableCellRendererComponent(table, 
                    value, isSelected, hasFocus, row, column);
            // configure myself as appropriate
            setBackground(comp.getBackground());
            setForeground(comp.getForeground());
            setBorder(((JComponent) comp).getBorder());
            return this;
        }
    }
    

    这在每个核心 LAF 中看起来都不错……除了 Nimbus:我们在行中的区域周围有一个小的白色边框,带有备用颜色。乍一看似乎是一个不透明度缺陷,哦,是的 - 忘记将不透明度显式设置为 true

    // initial config
    ...
    setOpaque = true;
    

    现在我们在正常颜色的行中的区域周围有一个小的黑色边框。奇怪的是,黑暗是 viewport 的颜色 - ?

    在一天结束时(跳过时间 :-) 事实证明 Nimbus 中的 textArea 有一个特殊的 ui 状态 NOTINSCROLLPANE。在那种状态下,TextAreaPainter 填充了一个减少了大约 2px 插图的区域(不知道为什么)。当不用于渲染时,将 opacity 设置为 true 足以使其填充整个区域。当用于渲染时,除了...将其添加到 JViewport(从而伪造状态)并将视口作为渲染组件返回(不知道为什么会有这种差异)之外,没有任何帮助。

    public static class TextAreaRenderer2 extends JTextArea implements
            TableCellRenderer {
    
        private TableCellRenderer delegate;
        JComponent parent;
        public TextAreaRenderer2(TableCellRenderer delegate) {
            this.delegate = delegate;
            // initial config
            Font font = new Font("Aparajita", Font.BOLD + Font.ITALIC, 16);
            setFont(font);
            setLineWrap(true);
            setWrapStyleWord(true);
            parent = new JViewport();
            parent.add(this);
        }
    
        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            // configure content
            setText((String) value);
            // get a configured component from the delegate
            Component comp = delegate.getTableCellRendererComponent(table, 
                    value, isSelected, hasFocus, row, column);
            // configure myself as appropriate
            setBackground(comp.getBackground());
            setForeground(comp.getForeground());
            setBorder(((JComponent) comp).getBorder());
            // return the viewport we are added to
            return parent;
        }
    }
    

    【讨论】:

    • +1 很高兴我没有在周末开始讨论这个问题 ;-)
    最近更新 更多