Pregunta

OK, yo sé cómo hacer que una simple costumbre JComponent.Sé cómo reemplazar un TableCellRenderer.Me parece que no puede combinar los dos.

Aquí una muestra JComponent He creado:

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

Funciona bien como un independiente JComponent.Yo llame setXval(something) y se actualiza bien.(edición:Tengo un Swing Timer que las actualizaciones de los datos de forma periódica)

Pero si este componente es algo que yo vuelva en TableCellRenderer.getTableCellRendererComponent(), luego vuelve a pintar cuando hago clic en la celda en cuestión.¿Por qué?Debo estar dejando fuera algo muy simple.

¿Fue útil?

Solución

Por motivos de rendimiento de un JTable reutiliza componentes de procesador de pintar varias celdas - por lo que cuando se ve el componente en el JTable que no está realmente allí en el sentido tradicional de un componente en un recipiente que está presente en un lugar. Esto significa que llamar a repaint () en el componente procesador no hace nada.

La opción más eficaz sería la de almacenar el valor entero de la barra en su TableModel. Su TableCellRenderer sería entonces algo como esto:

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

A continuación, puede cambiar el número entero en su TableModel y sería desencadenar un repintado de la barra (puede que tenga un dependiente TableModel.fireTableCellUpdated sobre la aplicación TableModel que está utilizando).

Otros consejos

Los dos (Russ Hayward y Andrew) ayudaron, la clave era esencialmente para hacer lo siguiente:

  • almacenar el estado que se hace visible en el propio TableModel, no en el procesador
  • asegurarse de que cuando el estado de la TableModel, fireTableCellUpdated() se llama
  • tener solamente un objeto TableCellRenderer y un JComponent para mi columna personalizada (no uno por celda)
    • dentro TableCellRenderer.getTableCellRendererComponent() almacén de estado de la celda con el propósito de ser renderizado poco después (almacenamiento a largo plazo está en el TableModel)
    • proporcionar ese estado a la JComponent
    • devolver el JComponent
    • override JComponent.PaintComponent()
  • Una posibilidad es conveniente para un intérprete personalizado para extender y aplicar JComponent TableCellRenderer, a continuación, en return this; almacenar el estado de la célula y <=>

Este es el pasaje relevante de mi código que ahora trabaja:

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

Si comete una mesa con 3 filas dicen, cada uno con un XVal diferente, entonces lo hace inicialmente renderizador correctamente, es decir, cada célula tiene un bar de aspecto diferente?

Cuando usted dice que no vuelva a pintar a menos que haga clic en él, ha ocurrido algo a sus datos subyacente que debería haber causado la presentación visual de los datos (la barra prestado) para cambiar?

Si cambian los datos, pero la tabla no viniese volver a hacer, entonces yo diría que su TableModel no está funcionando adecuadamente.

subyace a los cambios de datos -> cambios TableModel -> dispara TableModelEvent -> vuelve a renderizar JTable

Mire la TableModel tuturial: http: / /java.sun.com/docs/books/tutorial/uiswing/components/table.html#data

para asegurarse de que está haciendo todo lo correcto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top