Java 在TableCellRenderer中使用自定义Swing JComponent

Java 在TableCellRenderer中使用自定义Swing JComponent,java,swing,jcomponent,tablecellrenderer,Java,Swing,Jcomponent,Tablecellrenderer,好的,我知道如何制作一个简单的定制组件。我知道如何覆盖TableCellRenderer。我似乎无法将两者结合起来 下面是我创建的一个示例JComponent public static class BarRenderer extends JComponent { final private double xmin; final private double xmax; private double xval; public BarRenderer(double

好的,我知道如何制作一个简单的定制组件。我知道如何覆盖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(某物)
,它更新得很好。(编辑:我有一个摆动计时器,定期更新数据)


但是如果这个组件是我在TableCellRenderer.GetTableCellRenderComponent()中返回的,那么它只在我单击相关单元格时重新绘制。有什么好处?我必须略去一些非常简单的东西。

如果你制作一个包含3行的表格,每行都有一个不同的Xval,那么它一开始是否正确,这意味着每个单元格都有一个不同的外观条

当您说除非单击它,否则它不会重新绘制时,您的基础数据是否发生了本应导致数据(渲染条)的视觉显示发生更改的情况

如果数据发生了更改,但表没有立即重新呈现,那么我会说您的TableModel工作不正常

基础数据更改->表格模型更改->激发表格模型事件->JTable重新呈现

查看TableModel tuturial:


确保你做的每件事都是正确的。

如果你做了一个表,比如说有3行,每行都有不同的Xval,那么它一开始是否正确,这意味着每个单元格都有不同的外观条

当您说除非单击它,否则它不会重新绘制时,您的基础数据是否发生了本应导致数据(渲染条)的视觉显示发生更改的情况

如果数据发生了更改,但表没有立即重新呈现,那么我会说您的TableModel工作不正常

基础数据更改->表格模型更改->激发表格模型事件->JTable重新呈现

查看TableModel tuturial:


为了确保您所做的一切都是正确的。

出于性能原因,JTable重用渲染器组件来绘制多个单元格-因此,当您在JTable中看到组件时,它实际上并不在某个位置的容器中的组件的传统意义上。这意味着在渲染器组件上调用repaint()不会产生任何效果

最有效的选择是在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实现).

出于性能原因,JTable重用渲染器组件来绘制多个单元格-因此,当您在JTable中看到组件时,它实际上并不在某个位置的容器中的组件的传统意义上。这意味着在渲染器组件上调用repaint()不会产生任何效果

最有效的选择是在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实现)。

在双方(Russ Hayward和Andrew)的帮助下,关键是执行以下操作:

  • 将要使其可见的状态存储在TableModel本身中,而不是在渲染器中
  • 确保当TableModel的状态更改时,调用
    fireTableCellUpdated()
  • 我的自定义列只有一个TableCellRenderer对象和一个JComponent(不是每个单元格一个)
    • TableCellRenderer.getTableCellRendererComponent()中存储单元格的状态,以便稍后进行渲染(长期存储在TableModel中)
    • 向JComponent提供该状态
    • 返回JComponent
    • 重写
      JComponent.PaintComponent()
  • 一种方便的方法是自定义呈现程序扩展JComponent并实现TableCellRenderer,然后在
    TableCellRenderer.getTableCellRenderComponent()中存储单元格的状态并
    返回该状态
下面是我的代码的相关摘录,现在可以使用了:

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;
    }
}
你们两位(Russ Hayward和Andrew)都提供了帮助,关键是要做到以下几点:

  • 将要使其可见的状态存储在TableModel本身中,而不是在渲染器中
  • 确保当TableModel的状态更改时,调用
    fireTableCellUpdated()
  • 我的自定义列只有一个TableCellRenderer对象和一个JComponent(不是每个单元格一个)
    • TableCellRenderer.getTableCellRendererComponent()中存储单元格的状态,以便稍后进行渲染(长期存储在TableModel中)
    • 向JComponent提供该状态
    • 返回JComponent
    • 重写
      JComponent.PaintComponent()
  • 一种方便的方法是自定义呈现程序扩展JComponent并实现TableCellRenderer,然后在
    TableCellRenderer.getTableCellRenderComponent()中存储单元格的状态并
    返回该状态
下面是我的代码的相关摘录,现在可以使用了:

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;
    }
}

听起来是个可能的解决方案。。。我认为TableModel.fireTableCellUpdated听起来像是这里的关键。听起来像是一个可能的解决方案。。。我认为TableModel.fireTableCellUpdated听起来像是这里的关键。