Java JTable 单元格渲染器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6644922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JTable Cell Renderer
提问by Diesal11
I'm following some code I found, (Yes I understand how it works) It's from here :Code Link
我正在关注我发现的一些代码,(是的,我明白它是如何工作的)它来自这里:代码链接
What i'm trying to do is set a cells Foreground color if the cells 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 the 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 it isn't changing, if I set any cells value to "yellow"
问题是它不会改变,如果我将任何单元格值设置为“黄色”
Thanks in advance!
提前致谢!
采纳答案by Hovercraft Full Of Eels
Is your renderer ever even used? You make it the default renderer for cells containing String, but have you overloaded your model's getColumnClass
method so that it knows that some of the cells hold Strings?
你的渲染器有没有用过?您使它成为包含字符串的单元格的默认渲染器,但是您是否重载了模型的getColumnClass
方法,以便它知道某些单元格包含字符串?
So first I'd use println statements to see if the renderer is even being called and if not, I'd override my model's method as noted above.
所以首先我会使用 println 语句来查看渲染器是否被调用,如果没有,我将如上所述覆盖我的模型方法。
Edit 1
Also your if results are bound to be strange. In the if portion you change the forground and in the else you change the background -- makes no sense. You probably should do complementary changes in state in the if vs. the else blocks, not orthogonal changes.
编辑 1
你的 if 结果也一定很奇怪。在 if 部分更改前景,在 else 部分更改背景 - 没有意义。您可能应该在 if 与 else 块中对状态进行补充更改,而不是正交更改。
Edit 2
For example:
编辑 2
例如:
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;
}
}
回答by Heisenbug
Add this line:
添加这一行:
c.setOpaque(true);
The Component returned by getTableCellRendererComponent must be opaque in order to see changes on background and foreground color. The problem here is also another: you are extending DefaultTableCellRenderer (that is a JComponent) but you are returning a Component that hasn't setOpaque method. I would refactor your code like this:
getTableCellRendererComponent 返回的 Component 必须是不透明的,以便查看背景和前景色的变化。这里的问题也是另一个问题:您正在扩展 DefaultTableCellRenderer(即 JComponent),但您正在返回一个没有 setOpaque 方法的组件。我会像这样重构你的代码:
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;
}
回答by Syed Maruf
Here is a simple solution, use TableCellRenderer as an inner class.
这是一个简单的解决方案,使用 TableCellRenderer 作为内部类。
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;
}
});