更改单元格颜色而不更改其他单元格中的颜色(Jtable)

Posted

技术标签:

【中文标题】更改单元格颜色而不更改其他单元格中的颜色(Jtable)【英文标题】:Changing Cell Color without changing color in other cells (Jtable) 【发布时间】:2014-08-24 16:06:22 【问题描述】:

假设我们有一个 31 列和 10 行的 JTable。 我想将 2 Column 4 行的颜色更改为红色。 在我这样做之后,更改另一个单元格的颜色,而不会丢失我之前的单元格的颜色。

我尝试了以下方法但没有成功:

public class CellR extends DefaultTableCellRenderer 

     public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus,
            int row, int column) 

        setForeground(Color.white);
        if(row == TestHotel.v.getRow()  && column == TestHotel.v.getCol())
            // Only for specific cell
            // c.setFont(/* special font*/);
            // you may want to address isSelected here too
            setForeground(Color.BLACK);
            setBackground(Color.RED);
          
         return this;

如果我在第一次工作时调用渲染器...但是如果我想更改另一种单元格颜色,我将失去第一个。

【问题讨论】:

这些信息不足以调试您的问题。请提供MCVE。 同意 SSCCE/MCVE,简短,可运行,可编译,在局部变量中为 JTable/XxxTableModel 硬编码值,因为看起来像 if(row == TestHotel.v.getRow() && column == TestHotel.v.getCol()) 返回银河系中的恒星数量 此表单中的注释代码可能适用于未排序或过滤的 JTables 视图 每次修改都会重新绘制表格。然后你需要保存所有你想改变颜色的单元格。 【参考方案1】:

表格和列表中的单元格渲染器就像“邮票”一样使用。 一个组件用于绘制所有单元格。另见Concepts: Editors and Renderers。如果您想保留有关“突出显示”单元格的信息,您必须以某种方式存储它们。

一个例子(基于 cmets 扩展):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class CellRendererTest

    public static void main(String[] args)
    
        SwingUtilities.invokeLater(new Runnable()
        
            @Override
            public void run()
            
                createAndShowGUI();
            
        );
    

    private static void createAndShowGUI()
    
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        String[] columnNames = 
            "First Name", "Last Name", "Sport" ;
        Object[][] data = 
            "Kathy", "Smith", "Snowboarding" ,
            "John", "Doe", "Rowing" ,
            "Sue", "Black", "Knitting",
            "Jane", "White", "Speed reading",
            "Joe", "Brown", "Pool"
        ;
        final JTable table = new JTable(data, columnNames);

        final ColoringCellRenderer cellRenderer = new ColoringCellRenderer(); 
        TableColumnModel columnModel = table.getColumnModel();
        int cc = columnModel.getColumnCount();
        for (int c=0; c<cc; c++)
        
            TableColumn column = columnModel.getColumn(c);
            column.setCellRenderer(cellRenderer);
        
        JScrollPane scrollPane = new JScrollPane(table);
        f.getContentPane().setLayout(new BorderLayout());
        f.getContentPane().add(scrollPane, BorderLayout.CENTER);

        JButton addRandomColorButton = new JButton("Add random color");
        addRandomColorButton.addActionListener(new ActionListener()
        
            private Random random = new Random(0);
            @Override
            public void actionPerformed(ActionEvent e)
            
                int rows = table.getRowCount();
                int cols = table.getColumnCount();
                int row = random.nextInt(rows);
                int col = random.nextInt(cols);
                int r = random.nextInt(255);
                int g = random.nextInt(255);
                int b = random.nextInt(255);
                cellRenderer.setCellColor(row, col, new Color(r,g,b));
                table.repaint();
            
        );
        f.getContentPane().add(addRandomColorButton, BorderLayout.SOUTH);

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    



class ColoringCellRenderer extends DefaultTableCellRenderer

    private final Map<Point, Color> cellColors = new HashMap<Point, Color>();

    void setCellColor(int r, int c, Color color)
    
        if (color == null)
        
            cellColors.remove(new Point(r,c));
        
        else
        
            cellColors.put(new Point(r,c), color);
        
    

    private Color getCellColor(int r, int c)
    
        Color color = cellColors.get(new Point(r,c));
        if (color == null)
        
            return Color.WHITE;
        
        return color;
    

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
    
        super.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, column);
        Color color = getCellColor(row, column);
        setBackground(color);
        return this;
    


编辑:其余部分来自原始答案,仅使用单个单元格颜色。上面的新版本更完整(也更强大,因为它可以模拟单色渲染器),但为了完整起见,我将把它留在这里

这可以通过像这样的渲染器来实现:

class ColoringCellRenderer extends DefaultTableCellRenderer

    private final Set<Point> highlightedCells = new HashSet<Point>();

    void setHighlighted(int r, int c, boolean highlighted)
    
        if (highlighted)
        
            highlightedCells.add(new Point(r,c));
        
        else
        
            highlightedCells.remove(new Point(r,c));
        
    

    private boolean isHighlighted(int r, int c)
    
        return highlightedCells.contains(new Point(r,c));
    

    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
    

        if (isHighlighted(row,  column))
        
            setForeground(Color.BLACK);
            setBackground(Color.RED);
        
        else
        
            setForeground(Color.BLACK);
            setBackground(Color.WHITE);
        
        return this;
    

然后您可以创建此渲染器的实例,并添加或删除要突出显示的单元格:

ColoringCellRenderer r = new ColoringCellRenderer();
// Assign renderer to table...
...

// Later, highlight cells:
r.setHighlighted(4,2,true);
r.setHighlighted(6,1,true);
r.setHighlighted(1,5,false);
...

如果您希望单元格的颜色不同,您可以将Set 替换为将特定Map 映射到特定的Point(表示单元格的行/列)到Color 对象。

【讨论】:

谢谢..这正是我想要的..:) 你能否提供更多关于我如何用 2 种颜色制作它的信息...(我是这方面的初学者) @user3801896 我相应地扩展了答案 好的...我明白了..谢谢您的帮助:D @Marco13 不同意 (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 太费劲了,prepareRenderer 使用简单,逐个测试,改成JTables 视图应该是,必须包裹进 if (table.getRowCount > 0) @mKorbel 不完全确定您的意思。可以覆盖此方法,但必须将单元格->颜色映射存储在某个地方(我更喜欢使用渲染器而不是子类化 JTable,但这可能是这里的一个细节......)【参考方案2】:

你需要在你想要的列上设置单元格渲染器。

如果您说希望第 2 行第 4 列 的单元格颜色为红色,则应将渲染器设置在第 4 列。您甚至可以在所有列上设置渲染器。

那么您所要做的就是对行进行 if-check。 IE。如果(行 == 4)。但我假设您将从 TestHotel.v 对象中获取您的值。

【讨论】:

但是如果我在特定列中设置让我们说数字 2 并且我第一次更改第 10 行中的单元格。如果下次我想更改第 2 列中的第 11 行我会松开以前的编辑...我认为.. 您只需要更新表 updateUI(),它应该尊重模型的任何更改。如果您的 TestHotl.v 中的值发生了变化,那么您应该会看到这些变化。

以上是关于更改单元格颜色而不更改其他单元格中的颜色(Jtable)的主要内容,如果未能解决你的问题,请参考以下文章

AG-Grid:如何根据同一行中其他单元格中的值更改单元格的颜色

如何通过单击更改集合视图单元格中的标签颜色

如果单元格中的计算值发生变化,则更改单元格颜色

在不更改边框颜色的情况下更改 GridView 单元格中的文本颜色

在tableview单元格中更改like按钮的颜色

分组 UITableView 自定义绘制单元格,而不更改背景颜色?