【问题标题】:Java JTable change cell colorJava JTable 更改单元格颜色
【发布时间】:2011-08-06 02:48:21
【问题描述】:

我想制作一个可编辑的表格,然后检查数据以确保其有效。我不确定如何更改一个单元格的颜色。我想得到一个单元格,例如 (0,0) 并将前景着色为红色。我已经阅读了 SO 和 Oracle 上关于自定义 ColorRenderer 的其他帖子,但我只是不明白我将如何使用它。

谢谢。

【问题讨论】:

    标签: java swing colors jtable


    【解决方案1】:

    您可以扩展 DefaultTableCellRenderer,覆盖 getTableCellRendererComponent 并调用类似的东西

    if (myConditions) setBackground(myColor);
    

    在条件适用时返回“this”之前,但由于 DefaultTableCellRenderer.setBackGround 的编码方式,它具有更改默认背景颜色的非常烦人的副作用。

    我发现的技巧是在一个名为 HackedDefaultTableCellRenderer 的类中完全复制 DefaultTableCellRenderer 的代码,添加一个直接调用组件的 setBackground 实现的方法:

    public void setComponentBackground(Color c) {
        super.setBackground(c);
    }
    

    然后从这个被黑的类而不是从 DefaultTableCellRenderer 派生我的自定义渲染,最后在我的自定义 getTableCellRendererComponent 中调用 setComponentBackground 而不是 setBackground。

    缺点是这个 HackedDefaultTableCellRenderer 依赖于 DefaultTableCellRenderer 的快照。

    【讨论】:

      【解决方案2】:

      我相信在表格中进行着色的正确方法是通过ColorHighlighter表格渲染器在同一列中渲染不同颜色时存在问题。

      以下是如何使用荧光笔的示例。在这种情况下,它用于突出显示不可编辑的单元格。

      public class IsCellEditablePredicate implements HighlightPredicate {
      
         private JXTable table;
      
         public IsCellEditablePredicate (final JXTable table) {
             this.table = table;
         }
      
         @Override
         public boolean isHighlighted(Component component, ComponentAdapter componentAdapter) {
      
              return !table.isCellEditable(componentAdapter.row,
                componentAdapter.column);
         }
      }
      

      然后在设置表格的代码中添加荧光笔及其颜色参数:

       ColorHighlighter grayHighlighter = new ColorHighlighter(new IsCellEditablePredicate(table));
      
          grayHighlighter.setBackground(Color.LIGHT_GRAY);
          grayHighlighter.setForeground(table.getForeground());
          grayHighlighter.setSelectedBackground(table.getSelectionBackground().darker());
          grayHighlighter.setSelectedForeground(table.getSelectionForeground().darker());
      
          table.setHighlighters(grayHighlighter);
      

      【讨论】:

      • 你用粗体表示的句子到底是什么意思?可以举个例子吗?
      【解决方案3】:
      @Override
      public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
              int row, int col) {
          Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
          int control = row;
          control = control % 2;
          control = (control == 0) ? 1 : 0;
          if (control == 1) {
              c.setBackground(Color.green);
          } else {
              c.setBackground(Color.cyan);
          }
          return c;
      }
      

      【讨论】:

      • 欢迎来到 Stack Overflow!请不要把你的源代码扔在这里。友善一点,并尝试对您的答案进行漂亮的描述,以便其他人会喜欢并支持它。见:How do I write a good answer?
      【解决方案4】:

      这是为 jTable 中的特定列或单元格着色的最简单方法。

      首先创建一个简单的CustomRenderer

      class CustomRenderer extends DefaultTableCellRenderer <br />
      {
          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);
              setForeground(Color.blue); >
              return c;
          }
      }
      

      此代码获取要渲染的单元格列

      TableColumn col = tblExamHistoryAll.getColumnModel().getColumn(5);
      DefaultTableModel model3 = (DefaultTableModel)tblExamHistoryAll.getModel();
      col.setCellRenderer(new CustomRenderer());
      

      这是从您的表中清除所有先前的行。如果您不想要它们,只需删除这些行

      model3.getDataVector().removeAllElements();
      model3.fireTableDataChanged();
      

      【讨论】:

      • -1 for fireXX 从外面看(想知道是不是你的确切same incorrect answer - 同名,新帐户?)
      【解决方案5】:

      我想制作一个可编辑的表格,然后检查数据以确保其有效。

      另一种方法是在将数据保存到表模型之前对其进行编辑,以防止输入无效数据。

      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      import javax.swing.text.*;
      import javax.swing.event.*;
      import javax.swing.border.*;
      import javax.swing.table.*;
      
      public class TableEdit extends JFrame
      {
          TableEdit()
          {
              JTable table = new JTable(5,5);
              table.setPreferredScrollableViewportSize(table.getPreferredSize());
      
              JScrollPane scrollpane = new JScrollPane(table);
              getContentPane().add(scrollpane);
      
              //  Use a custom editor
      
              TableCellEditor fce = new FiveCharacterEditor();
              table.setDefaultEditor(Object.class, fce);
          }
      
          class FiveCharacterEditor extends DefaultCellEditor
          {
              FiveCharacterEditor()
              {
                  super( new JTextField() );
              }
      
              public boolean stopCellEditing()
              {
                  try
                  {
                      String editingValue = (String)getCellEditorValue();
      
                      if(editingValue.length() != 5)
                      {
                          JTextField textField = (JTextField)getComponent();
                          textField.setBorder(new LineBorder(Color.red));
                          textField.selectAll();
                          textField.requestFocusInWindow();
      
                          JOptionPane.showMessageDialog(
                              null,
                              "Please enter string with 5 letters.",
                              "Alert!",JOptionPane.ERROR_MESSAGE);
                          return false;
                      }
                  }
                  catch(ClassCastException exception)
                  {
                      return false;
                  }
      
                  return super.stopCellEditing();
              }
      
              public Component getTableCellEditorComponent(
                  JTable table, Object value, boolean isSelected, int row, int column)
              {
                  Component c = super.getTableCellEditorComponent(
                      table, value, isSelected, row, column);
                  ((JComponent)c).setBorder(new LineBorder(Color.black));
      
                  return c;
              }
      
          }
      
          public static void main(String [] args)
          {
              JFrame frame = new TableEdit();
              frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
              frame.pack();
              frame.setLocationRelativeTo( null );
              frame.setVisible(true);
          }
      }
      

      【讨论】:

      • 这可能是我正在寻找的,我会试一试,让你知道。我确实有一个保存按钮,用于在保存之前检查所有数据是否有效。我希望能够保存有效的数据并跳过无效的数据。谢谢!
      【解决方案6】:

      最直接的方法是通过扩展DefaultTableCellRenderer 并将getTableCellRendererComponent 方法覆盖为setBackground( Color.RED ) 来编写一个简单的TableCellRenderer。例如:

      final JTable table = new JTable(...);
      table.setCellRenderer( new DefaultTableCellRenderer() {
          public Component getTableCellRenderer(JTable table, Object value, ...) {
              super.getTableCellRenderer(...);
      
              if ( value should be highlighted ) {
                  setBackground( Color.RED );
              }
              return this;
          }
      });
      

      【讨论】:

      • 不——那是不完整的:DefaultTableCellEditor 是一个损坏的实现,它表现出臭名昭著的“颜色记忆”——当触摸一次颜色时,你必须总是这样做,即在 if
      • @kleopatra 你是对的,应该有一个else 将颜色重置为黑色。此外,JTable 上没有 setCellRenderer 方法,因此这是一个不完整的示例。我的意图是,它会向 OP 展示足以让他们走上正确的道路,并且他们可以自己学习这些小细节。
      【解决方案7】:

      假设您想用不同颜色渲染的单元格代表一种状态(我将以 Rejected 和 Approved 为例)。然后,我将在我的表模型中实现一个名为 getStatus(int row) 的方法,该方法返回任何给定行的状态。

      然后,当它到位时,我将着手创建一个单元格渲染器,负责渲染单元格所属的列。单元格渲染器将是以下代码行中的内容。

      public class StatusColumnCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
      
          //Cells are by default rendered as a JLabel.
          JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
      
          //Get the status for the current row.
          CustomTableModel tableModel = (CustomTableModel) table.getModel();
          if (tableModel.getStatus(row) == CustomTableModel.APPROVED) {
            l.setBackground(Color.GREEN);
          } else {
            l.setBackground(Color.RED);
          }
      
        //Return the JLabel which renders the cell.
        return l;
      
      }
      

      然后,当渲染器就位时,只需使用以下代码将渲染器“应用”到表格:

      Table.getColumnModel().getColumn(columnIndex).setCellRenderer(new StatusColumnCellRenderer());
      

      关于使单元格可编辑,只需在表格模型中实现isCellEditable(int rowIndex, int columnIndex) 方法。您还需要实现该方法 setValueAt(Object value, int rowIndex, int columnIndex) 如果您想保留用户提供的值(我假设您这样做!)。

      【讨论】:

      • 另外:如果您愿意,也可以避免在表模型中实现 getStatus() 方法。比如说,如果你的表模型的 getValueAt(int rowIndex, int columnIndex) 将状态作为字符串返回(“APPROVED”,“REJECTED”),那么你可以简单地让渲染来检查提供的值 [...]RendererComponent(table, value , boolean[...]) 并基于此更改单元格的颜色。那么您就不需要绕道“绕道”到表模型来获取当前行/列的状态。这实际上可能是最简单的方法......
      • 最后一点提示:如果您要采用实现 getStatus(int row) 的解决方案,请确保使用 table.convertRowIndexToModel(int row) 转换行索引。提供给 getTableCellRendererComponent() 的行是视图索引,如果由于排序而改变了行的顺序,它可能与模型索引不同。
      猜你喜欢
      • 2011-11-03
      • 2018-08-20
      • 2011-08-14
      • 2011-09-24
      • 2014-08-24
      • 2019-09-09
      • 2020-08-25
      • 2013-02-23
      相关资源
      最近更新 更多