JTable Cell Renderer

I follow the code I found (Yes, I understand how this works) This is from here: Link to code

What I'm trying to do is set the cells Foreground color if the cell value is set to "yellow"

Here is my code:

public class Board extends JPanel{ private static final long serialVersionUID = 1L; int boardHeight = 20; int boardWidth = 10; JTable table; public Board() { table = new JTable(this.boardHeight, this.boardWidth); table.setDefaultRenderer(String.class, new BoardTableCellRenderer()); table.setFocusable(false); table.setShowGrid(false); table.setRowMargin(0); table.setIntercellSpacing(new Dimension(0,0)); table.setRowSelectionAllowed(false); table.setVisible(true); this.add(table); this.setPreferredSize(new Dimension(table.getPreferredSize().width, (table.getPreferredSize().height + 85))); } public void paint(Graphics g) { table.setRowHeight(20); for (int x = 0; x < this.table.getColumnCount(); ++x) { TableColumn col = this.table.getColumnModel().getColumn(x); col.setPreferredWidth(20); } } } 

And cell renderer

 public class BoardTableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; 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); String s = table.getModel().getValueAt(row, col).toString(); if (s.equalsIgnoreCase("yellow")) { c.setForeground(Color.YELLOW); } else { c.setForeground(Color.WHITE); } return c; } } 

The problem is that it does not change if I set the cell value to yellow

Thanks in advance!

+8
java swing jtable tablecellrenderer
source share
3 answers

Is your render ever used? You make this the default renderer for cells containing String, but have you overloaded the getColumnClass model method so that it knows some cells contain strings?

So, first I would use println instructions to see if the visualizer would even be called, and if not, I would override my model method, as described above.

Change 1
Also your results will be strange. In the part where you change the fold, and in the other - the background - it makes no sense. You should probably make additional state changes in if and else blocks, and not in orthogonal changes.

Edit 2
For example:

 import java.awt.*; import java.util.Random; import javax.swing.*; import javax.swing.table.*; public class Board extends JPanel { private static final long serialVersionUID = 1L; int boardHeight = 20; int boardWidth = 10; JTable table; Random random = new Random(); public Board() { setLayout(new BorderLayout()); // !! DefaultTableModel model = new DefaultTableModel(boardHeight, boardWidth) { @Override public Class<?> getColumnClass(int columnIndex) { return String.class; } }; // !! table = new JTable(this.boardHeight, this.boardWidth); table = new JTable(model); for (int row = 0; row < model.getRowCount(); row++) { for (int col = 0; col < model.getColumnCount(); col++) { String s = random.nextBoolean() ? "red" : "yellow"; model.setValueAt(s, row, col); } } table.setDefaultRenderer(String.class, new BoardTableCellRenderer()); table.setFocusable(false); table.setShowGrid(false); table.setRowMargin(0); table.setIntercellSpacing(new Dimension(0, 0)); table.setRowSelectionAllowed(false); table.setVisible(true); this.add(table); this.setPreferredSize(new Dimension(table.getPreferredSize().width, (table.getPreferredSize().height + 85))); } private static void createAndShowUI() { JFrame frame = new JFrame("Board"); frame.getContentPane().add(new Board()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } class BoardTableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; 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); Object valueAt = table.getModel().getValueAt(row, col); String s = ""; if (valueAt != null) { s = valueAt.toString(); } if (s.equalsIgnoreCase("yellow")) { c.setForeground(Color.YELLOW); c.setBackground(Color.gray); } else { c.setForeground(Color.black); c.setBackground(Color.WHITE); } return c; } } 
+9
source share

Add this line:

 c.setOpaque(true); 

The component returned by getTableCellRendererComponent must be opaque to see changes in background and foreground color. The problem here is also different: you extend the DefaultTableCellRenderer (this is a JComponent), but you return a component that does not have the setOpaque method. I would reorganize your code as follows:

 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row,int col) { String s = table.getModel().getValueAt(row, col).toString(); this.setOpaque(true); if (s.equalsIgnoreCase("yellow")) { this.setForeground(Color.YELLOW); } else { this.setBackground(Color.WHITE); } return this; } 
+3
source share

Here is a simple solution, use TabaleCellRendere as an inner class.

  myTable.setDefaultRenderer(Object.class, new TableCellRenderer() { JLabel comp = new JLabel(); String val; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { comp.setOpaque(true); comp.setForeground(Color.BLACK); // text color if (value != null) { val = value.toString(); comp.setText(val); if (val.equalsIgnoreCase("red")) { comp.setBackground(Color.RED); } else if (val.equalsIgnoreCase("yellow")) { comp.setBackground(Color.YELLOW); } else if (val.equalsIgnoreCase("green")) { comp.setBackground(Color.GREEN); } else { comp.setBackground(Color.WHITE); } } return comp; } }); 
+1
source share

All Articles