Frage

OK, ich weiß, wie man eine einfache benutzerdefinierte JComponent zu machen. Ich weiß, wie eine Table außer Kraft zu setzen. Ich kann nicht scheinen, um die beiden zu verbinden.

Hier ist ein Beispiel JComponent I erstellt:

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

Es funktioniert als eigenständiges JComponent. Ich nenne setXval(something) und aktualisiert es einfach gut. (Edit: Ich habe einen Swing-Timer, der die Daten aktualisiert in regelmäßigen Abständen)

Aber wenn diese Komponente etwas, das ich in TableCellRenderer.getTableCellRendererComponent zurückkehren (), dann ist es nur neu zeichnet, wenn ich auf die betreffende Zelle klicken. Was gibt? Ich muss etwas wirklich einfach auslassen.

War es hilfreich?

Lösung

Aus Gründen der Performance wieder verwendet ein JTable Renderer Komponenten mehr Zellen zu malen - so, wenn Sie die Komponente in der JTable sehen es im traditionellen Sinne einer Komponente in einem Container nicht wirklich da ist, die an einem Ort vorhanden ist. Dies bedeutet, dass repaint () aufrufen auf dem Renderer Komponente tut nichts.

Die effektivste Möglichkeit wäre, den Integer-Wert der Bar in dem Tablemodel zu speichern. Ihre Table würde dann in etwa so aussehen:

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

Dann könnte man das Ganze Zahl in Ihrer Tablemodel ändern, und es wäre ein Neuzeichnen der Bar auslösen (Sie müssen möglicherweise einen TableModel.fireTableCellUpdated abhängig von der Implementierung Tablemodel Sie verwenden).

Andere Tipps

Sie beide (Russ Hayward und Andrew) geholfen, der Schlüssel war im Wesentlichen Folgendes zu tun:

  • den Zustand speichern, um in dem Tablemodel selbst, nicht in den Renderer
  • sichtbar gemacht werden
  • stellen Sie sicher, dass, wenn das Tablemodels des Zustandsänderung, fireTableCellUpdated() genannt wird
  • nur ein Table Objekt und ein JComponent für meine benutzerdefinierte Spalte (nicht eine pro Zelle)
    • innerhalb TableCellRenderer.getTableCellRendererComponent() Speicher der staatlichen Zelle zum Zweck der bald, nachdem sie Rendering (Langzeitlagerung ist in dem Tablemodel)
    • bieten diesen Zustand der JComponent
    • Rückkehr der JComponent
    • Überschreibung JComponent.PaintComponent()
  • eine bequeme Möglichkeit für einen benutzerdefinierten Renderer JComponent zu erweitern und implementieren Table, dann in TableCellRenderer.getTableCellRendererComponent() speichern Sie den Zustand der Zelle und return this;

Hier ist der relevante Auszug aus meinem Code, jetzt funktioniert:

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

Wenn Sie einen Tisch machen mit sagen, 3 Reihen, die jeweils eine andere XWert hat, dann ist es zunächst richtig Renderer, jede Zelle bedeutet eine andere suche Bar?

Wenn Sie sagen, dass es nicht, wenn Sie es nicht neu streichen klicken, hat etwas zu Ihren zugrunde liegenden Daten geschehen, die die visuelle Darstellung der Daten verursacht haben sollten (die gerenderte bar) zu ändern?

Wenn die Daten geändert, aber die Tabelle nicht immediatley wieder macht, dann würde ich sagen, dass Ihr Tablemodel nicht richtig funktioniert.

zugrunde liegenden Datenänderungen -> Tablemodel Änderungen -> feuert TableModelEvent -> JTable Wieder macht

Sehen Sie sich die Tablemodel tuturial: http: / /java.sun.com/docs/books/tutorial/uiswing/components/table.html#data

, um sicherzustellen, dass Sie alles richtig machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top