我试图能够在JTable中对单元格进行着色,但到目前为止,我只能在整个列上应用TableCellRenderer,这显然会出现故障。我有一个自定义JTable:
public class JColorTable extends JTable{
(...)
public void setCellColor(int col, int row, Color newColor) {
getColumnModel().getColumn(col).setCellRenderer(new ColorField(col, row, newColor, background));
repaint();
}
}
ColorField看起来像这样:
class ColorField extends DefaultTableCellRenderer {
(...))
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (row == newRow && column == newCol) {
l.setBackground(Color.red);
} else {
l.setBackground(defaultColor);
}
return l;
}
}
当我在列中有单个单元格时,这就像魅力一样,但是当我尝试为该列中的另一个单元格着色时,前一个单元格被删除(由于ColorField中的条件不适用于前一列)。
有没有办法只将ColorField应用于单个单元格而不是整个列?如果是这样,怎么样?我害怕找不到合适的东西。
答案 0 :(得分:3)
JTable
有一个方法getCellRenderer()
可以覆盖。当一个单元格需要渲染并在基于行和列返回一个单元格时调用它。
您的JTable
需要记录每个单元格使用哪个渲染器(按行和列)。 2D数组可以使用它,或者Map
,其中键是X,Y值。
添加一个方法来设置特定单元格上的渲染器(按行和列),然后就可以了。
class MyTable extends JTable {
// all the other JTable stuff goes here too ...
public TableCellRenderer getCellRenderer(int row, int column) {
TableCellRenderer myRenderer = getCustomRenderer(row, column);
if (myRenderer != null) {
return myRenderer;
}
// else...
return super.getCellRenderer(row, column);
}
private Map<Integer, Map<Integer, TableCellRenderer>> rendererMap = new ...;
public void setCustomRenderer(int row, int column, TableCellRenderer renderer) {
Map<Integer, TableCellRenderer> m1 = rendererMap.get(row);
if (m1 == null) {
m1 = new ...;
rendererMap.put(row, m1);
}
m1.put(column, renderer);
}
public TableCellRenderer getCustomRenderer(int row, int column) {
Map<Integer, TableCellRenderer> m1 = rendererMap.get(row);
if (m1 == null) {
return null;
}
return m1.get(column);
}
}
getTableCellRenderer
的默认版本使用在列上设置的渲染器(如果有),如果不是,则根据单元格内容的类使用渲染器。在许多情况下,默认单元格内容为Object
。这取决于使用的TableModel
。
答案 1 :(得分:3)
就个人而言,我会避免任何要求您延长JTable
的解决方案。主要原因是它使您的代码不那么容易,并且将渲染器与JTable
的特定实现紧密耦合。它可能适合您的需求,但就个人而言,我总是试图看到更大的图景/潜力/重用。
请记住,单元格渲染器绑定到表格列。它并不意味着能够逐个单元地提供自定义渲染,本身。您可以做的是,根据渲染器中的一系列条件为每个单元格提供渲染逻辑。
我可能会将一些条件/格式引擎组合在一起,您可以使用它来传递单元格值和坐标,然后根据引擎特定实现的需要做出决策。
class ColorField extends DefaultTableCellRenderer {
(...))
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// CellFormat is an object you create to hold the various aspects
// of the cell format
// You could also pass in the selected and focused flags if you
// needed them...
// getFormatEngine is a method you would write to provide
// to gain access to the format engine
CellFormat format = getFormatEngine().getFormatFor(value, row, column);
setBackground(format.getBackground());
setForeground(format.getForeground());
setFont(format.getFont());
// Any other properties you may wish to effect...
return this;
}
}
FormatEngine
将成为决定如何最佳格式化给定单元格的基础。它应该能够提供“默认”格式
这意味着您可以为特定单元格类型设计“默认”渲染器,但能够根据您的需要提供自定义渲染,而无需多个if
语句或扩展基础渲染
这也是条件格式引擎的基础,您可以针对给定值应用一系列条件,并根据结果返回适当的格式
答案 2 :(得分:0)
您需要列中每个单元格的一些颜色信息。此信息可以包含在值中:
class CellValue {
Color getBackgroundColor() { ... }
String getCellContent() { ... }
}
您的getTableCellRendererComponent()
方法可能如下所示:
CellValue cellValue = (CellValue) value;
Color bgColor = cellValue.getBackgroundColor();
String text = cellValue.getCellContent();
JLabel l = (JLabel) super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column);
l.setBackground(bgColor);
...
当然,您必须调整TableModel以存储CellValue实例。
答案 3 :(得分:0)
我认为实现这一目标的正确方法是通过ColorHighlighter。 这在the documentation中说。这是related issue in SO。
注意:如果表允许排序,则必需来实现相应的ComponentAdapter及其dapter.convertRowIndexToModel