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

时间:2012-03-07 19:18:21

标签: java swing 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)被着色?

3 个答案:

答案 0 :(得分:12)

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

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

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)然后调用超级:

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

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

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

答案 1 :(得分:6)

您忘记了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();
         }
      });
   }
}

答案 2 :(得分:4)

if添加else子句:

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

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