Domanda

OK, so come fare un semplice personalizzato JComponent. Io so come ignorare un TableCellRenderer. Io non riesco a combinare le due cose.

Ecco un esempio JComponent ho creato:

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

Funziona bene come un autonomo JComponent. Io lo chiamo setXval(something) e gli aggiornamenti più che bene. (Edit: ho un timer swing che aggiorna i dati periodicamente)

Ma se questo componente è qualcosa che torno a TableCellRenderer.getTableCellRendererComponent (), allora ridisegna solo quando clicco sul cellulare in questione. Ciò che dà? Devo essere lasciando fuori qualcosa di veramente semplice.

È stato utile?

Soluzione

Per motivi di prestazioni una JTable riutilizza componenti renderer di dipingere più celle - in modo che quando si vede il componente nel JTable non è in realtà lì nel senso tradizionale di un componente in un contenitore che è presente in una posizione. Ciò significa che chiama repaint () sul componente renderer non fa nulla.

L'opzione più efficace sarebbe quella di memorizzare il valore intero della barra nella vostra TableModel. Il tuo TableCellRenderer sarebbe quindi simile a questa:

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

Poi si potrebbe modificare l'intero nella vostra TableModel e sarebbe innescare un ridisegno della barra (potrebbe essere necessario un TableModel.fireTableCellUpdated dipende dall'implementazione TableModel che si sta utilizzando).

Altri suggerimenti

Entrambi voi (Russ Hayward e Andrea) ha aiutato, la chiave era essenzialmente per fare quanto segue:

  • memorizzare lo stato di essere reso visibile nel TableModel sé, non nel rendering
  • fare in modo che quando lo stato del TableModel, fireTableCellUpdated() è chiamato
  • avere solo una oggetto TableCellRenderer e una JComponent per la mia colonna personalizzata (non uno per cella)
    • all'interno TableCellRenderer.getTableCellRendererComponent() archivio di stato della cella ai fini di essere resa subito dopo (stoccaggio a lungo termine è in TableModel)
    • fornire questo stato al JComponent
    • restituire il JComponent
    • di override JComponent.PaintComponent()
  • una comoda possibilità è un renderer personalizzato per estendere e implementare JComponent TableCellRenderer, poi nel return this; si memorizza lo stato della cella e <=>

Ecco il relativo estratto del mio codice che funziona ora:

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

Se si effettua una tabella con dicono 3 file, ciascuno con un diverso ValX, allora vuol inizialmente renderer correttamente, il che significa ogni cella ha una diversa barra di ricerca?

Quando si dice che non si ridisegna a meno che non si fa clic su di esso, ha qualcosa è successo al tuo i dati di base che dovrebbe aver causato la visualizzazione dei dati (la barra resa) per cambiare?

Se i dati modificati, ma la tabella non dispensati ri-renderizzare, allora direi che il vostro TableModel non funziona correttamente.

sottostante modifiche dei dati -> modifiche TableModel -> incendi TableModelEvent -> re-rende JTable

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

per assicurarsi che si sta facendo tutto corretto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top