好的,我知道如何制作一个简单的自定义JComponent。我知道如何覆盖TableCellRenderer。我似乎无法将两者结合起来。
以下是我创建的示例JComponent
:
public static class BarRenderer extends JComponent
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
public void setXval(double x) {
this.xval = x;
repaint();
}
public double getXval() { return xval; }
}
它作为独立的JComponent工作正常。我打电话给setXval(something)
,它就更新了。 (编辑:我有一个定期更新数据的Swing Timer)
但是如果这个组件是我在TableCellRenderer.getTableCellRendererComponent()中返回的东西,那么它只会在我点击相关单元格时重新绘制。是什么赋予了?我必须遗漏一些非常简单的东西。
答案 0 :(得分:2)
出于性能原因,JTable重用渲染器组件来绘制多个单元格 - 因此当您在JTable中看到组件时,实际上并不存在传统意义上的某个位置存在的Container中的Component。这意味着在渲染器组件上调用repaint()不会执行任何操作。
最有效的选择是在TableModel中存储条形的Integer值。你的TableCellRenderer看起来像这样:
public class BarTableCellRenderer implements TableCellRenderer {
private final BarRenderer rendererComponent = new BarRenderer(0, 10);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rendererComponent.setXval((Integer)value);
return rendererComponent;
}
}
然后你可以更改TableModel中的Integer,它会触发条形图的重绘(你可能需要一个TableModel.fireTableCellUpdated依赖于你正在使用的TableModel实现)。
答案 1 :(得分:2)
你们两个人(拉斯·海沃德和安德鲁)帮忙,关键主要是要做到以下几点:
fireTableCellUpdated()
被称为TableCellRenderer.getTableCellRendererComponent()
内存储单元格的状态以便在不久之后进行渲染(长期存储位于TableModel中)JComponent.PaintComponent()
TableCellRenderer.getTableCellRendererComponent()
中存储单元格的状态和return this;
以下是我现在有效的代码摘录:
class TraceControlTableModel extends AbstractTableModel {
/* handle table state here */
// convenience method for setting bar value (table model's column 2)
public void setBarValue(int row, double x)
{
setValueAt(x, row, 2);
}
}
// one instance of BarRenderer will be set as the
// TableCellRenderer for table column 2
public static class BarRenderer extends JComponent
implements TableCellRenderer
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
super();
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
@Override
public Component getTableCellRendererComponent(JTable arg0,
Object value,
boolean isSelected, boolean hasFocus,
int row, int col)
{
// save state here prior to returning this object as a component
// to be painted
this.xval = (Double)value;
return this;
}
}
答案 2 :(得分:1)
如果你创建一个表3行的表,每行都有不同的Xval,那么它最初是否正确渲染,这意味着每个单元格都有不同的外观栏?
当你说它没有重新绘制除非你点击它,你的底层数据发生了什么事情应该导致数据的可视化显示(渲染条)改变?
如果数据发生了变化,但表格没有立即重新渲染,那么我会说你的TableModel无法正常工作。
基础数据更改 - > TableModel更改 - >触发TableModelEvent - > JTable重新渲染
查看TableModel tuturial:http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#data
确保你做的一切都是正确的。