繁体   English   中英

如何正确使用自定义渲染器绘制JTable中的特定单元格?

[英]How do I correctly use custom renderers to paint specific cells in a JTable?

我的GUI中有一个JTable组件,它显示算法的psuedocode 我想通过更改特定单元格的背景然后更改下面的单元格等来强调当前的执行行。

现在我的代码改变了JTable中所有单元格的背景,如下图所示:

JTable中

我用来存档这个当前状态的代码如下:

class CustomRenderer extends DefaultTableCellRenderer 
{
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
            JLabel d = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if((row == 0) && (column == 0))
                d.setBackground(new java.awt.Color(255, 72, 72));
            return d;
        }
    }

然后我调用jTable2.setDefaultRenderer(String.class, new CustomRenderer()); 在我的构造函数中。

我认为:

  • 在每个String类型的表格单元格上调用此方法。
  • 这只会改变位置(0,0)处单元格的颜色

如何修复我的代码,以便只有单元格(0,0)被着色?

这不是答案(*),对于两个答案的评论都太长了:两者都是正确的,因为else块是确保默认颜色用于不应该突出显示的单元格的重要因素。 他们在如何达到这个目标方面略有误解,两者都具有相同的整体效果:他们会错过任何特殊的颜色,例如由于选择,焦点,可编辑,d ...

他们通过不同的手段达到“未命中”,效果略有不同

setBackground(Color.WHITE);

设置为固定颜色,可能是也可能不是默认的“普通”表格背景

setBackground(null);

设置没有颜色导致显示“正常”背景颜色 - 由于DefaultTableCellRenderer的内部技巧是不透明的实现:-)

问题的基本原因(也称为臭名昭着的颜色内存,TM)是默认渲染器的异常糟糕的实现,使其基本上不可扩展:

 /**
 * Overrides <code>JComponent.setBackground</code> to assign
 * the unselected-background color to the specified color. 
 *
 * JW: The side-effect is documented and looks innocent enough :-) 
 */
public void setBackground(Color c) {
    super.setBackground(c); 
    unselectedBackground = c; 
}

// using that side-effect when configuring the colors in getTableCellRendererComp
// is what leads to the horrendeous problems
// in the following lines of the else (not selected, that is normal background color)
 Color background = unselectedBackground != null
           ? unselectedBackground : table.getBackground();
 super.setBackground(background);

看到这一点,除了使用SwingX及其灵活,干净,强大,一致的.. :-)渲染器支持之外,还有@Hovercraft的支持,但反过来:首先进行自定义着色(如果没有预期,则为null)然后调用super:

  @Override
  public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      if (myHighlightCondition) {
          setBackground(Color.RED);
      } else {
          setBackground(null);
      }
     super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
           row, column);
     return this;
  }

(*)毕竟,这个评论导致了答案,忘记了它可以在自定义渲染器级别上修复:-)

顺便说一句:抓住对渲染器的“第一次”调用是非常脆弱的,没有关于哪个单元格会发生的保护,可能是最后一列的最后一行。

您忘记了if块的其他部分,如果不是重要的行,则将背景绘制为默认值的代码:

        if (row == 0 && column == 0) {
           d.setBackground(new java.awt.Color(255, 72, 72));
        } else {
           d.setBackground(null);
        }

我的SSCCE

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;

public class TestJTable {
   private static int highlightedRow = 0;
   private static void createAndShowGui() {
      String[] columnNames = {"Program"};
      Object[][] rowData = {{"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}, 
            {"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}, 
            {"Row 1"}, {"Row 2"}, {"Row 3"}, {"Row 4"}};
      final JTable myTable = new JTable(rowData , columnNames );
      myTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
      {
         @Override
         public Component getTableCellRendererComponent(JTable table,
               Object value, boolean isSelected, boolean hasFocus, int row,
               int column) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
                  row, column);
            if (row == highlightedRow && column == 0) {
               c.setBackground(new java.awt.Color(255, 72, 72));
            } else {
               c.setBackground(null);
            }
            return c;
         }
      });


      JFrame frame = new JFrame("TestJTable");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new JScrollPane(myTable));
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);

      new Timer(1000, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            highlightedRow++;
            int rowCount = myTable.getRowCount();
            highlightedRow %= rowCount;
            myTable.repaint();
         }
      }).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

else子句添加到您if

if ((row == 0) && (column == 0)) {
    d.setBackground(new java.awt.Color(255, 72, 72));
}
else {
    d.setBackground(Color.WHITE);
}

请记住,相同的渲染器实例用于绘制所有单元格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM