好的,我知道如何制作一个简单的自定义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中的组件时,按照传统意义上的某个容器中存在于某个位置的容器,它实际上并不存在。这意味着在渲染器组件上调用repaint()不会执行任何操作。

最有效的选择是将Bar的Integer值存储在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中更改Integer,这将触发重新绘制栏(您可能需要TableModel.fireTableCellUpdated,具体取决于您使用的TableModel实现)。

关于java - 在TableCellRenderer中使用自定义的Swing JComponent,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/864707/

10-12 03:52