好的,我知道如何制作一个简单的自定义 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 计时器,可以定期更新数据)

但是,如果这个组件是我在 TableCellRenderer.getTableCellRendererComponent() 中返回的组件,那么它只会在我单击相关单元格时重新绘制。是什么赋予了?我一定遗漏了一些非常简单的东西。

有帮助吗?

解决方案

有关性能原因JTable中重用渲染器组件绘制多个单元格 - 因此,当你在JTable看到组件它实际上不是有在容器,其存在的位置处的组件的传统意义上的。这意味着,渲染器组件上调用重绘()什么都不做。

最有效的办法是酒吧的整数值存储在您的TableModel。那么你的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,它会触发条的重绘(你可能需要一个TableModel.fireTableCellUpdated取决于你使用的是TableModel的实现)。

其他提示

你们俩(拉斯·海沃德和安德鲁)都提供了帮助,关键是要做到以下几点:

  • 存储要在 TableModel 本身中可见的状态,而不是在渲染器中
  • 确保当 TableModel 的状态发生变化时, fireTableCellUpdated() 叫做
  • 只有 TableCellRenderer 对象和 我的自定义列的 JComponent(不是每个单元格一个)
    • 之内 TableCellRenderer.getTableCellRendererComponent() 存储单元格的状态以便稍后渲染(长期存储在 TableModel 中)
    • 将该状态提供给 JComponent
    • 返回 JComponent
    • 覆盖 JComponent.PaintComponent()
  • 一种方便的可能性是自定义渲染器扩展 JComponent 并实现 TableCellRenderer,然后在 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;
    }
}

如果你犯了一个表,说3排,每一个具有不同XVAL,然后它开始渲染器正确,这意味着每个单元都有不同的期待吧?

当你说它不重画,除非你点击它,有一些发生在本应引起数据的可视化显示(渲染栏),以改变你的基础数据?

如果数据发生变化,但不能将表immediatley重新渲染,那么我会说,你的TableModel的工作不正常。

底层数据的改变 - >的TableModel变化 - >触发TableModelEvent - >的JTable重新呈现

看为TableModel tuturial: HTTP:/ /java.sun.com/docs/books/tutorial/uiswing/components/table.html#data

,以确保你正在做的一切是正确的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top