# JTable, setValueAt, Laufzeitproblem



## Doc (20. Jan 2011)

Hallo,
ich hab eine Tabelle, die ich per Knopfdruck mit einer Schleife befülle mit:

table.setValueAt(textpane, i, 0);

Es handelt sich um ca. 200 Einträge. Das Ganze sollte schnell gehen.

Leider dauert es mehrere Sekunden bis die Schleife durchlaufen ist.
Wieso dauert das so lange? Kann man das ganze beschleunigen?
Vielleicht das Zeichnen der Tabelle verzögern und er Zeichnen wenn alle Einträge drin sind?


----------



## SlaterB (20. Jan 2011)

hast du irgendwelche Infos zu Besonderheiten?
sind das große Objekte, spielen Bilder mit, hast du ein eigenes Model was jeden Wert in die DB schreibt oder irgendwas interessantes ungewöhnliches?
ideal wäre wie immer ein lauffähiges Test-Programm

wenn die Zeile
> table.setValueAt(textpane, i, 0);
auskommentiert wird, dann gehts schnell, es ist sicher dass der Rest des Programms nicht die Sekunden verbraucht?
textpane ist nicht zufällig ein JTextPane?


----------



## Marco13 (20. Jan 2011)

200 sollte schnell gehen. Werden die Objekte auch in der Schleife erstellt, und dauert vielleicht DAS so lange? Und... das sind nicht wirklich TextPanes, oder? ???:L

EDIT: Nyäch... lahm...


----------



## André Uhres (20. Jan 2011)

Hallo Doc,

du könntest versuchen, ein neues Tabelmodel zu befüllen und es erst danach an die Tabelle mit [c]table.setModel(..)[/c] zu übergeben. Möglicherweise wird das Problem aber nicht (oder nicht nur) durch das Zeichnen verursacht. Ohne Code kann man das wohl nicht beurteilen.

Gruß,
André


----------



## Doc (21. Jan 2011)

mir fällt grad auf, es sind TextAreas 

Also hier die Schleife:

```
for(int i=0;i<200;i++){
   JTextArea textarea = new JTextArea();		
   textarea.setText("Test");
   textarea.setBackground(Color.BLUE);
   table.setValueAt(textarea, i, 2);
}
```

Sowohl mit JTextPanes als auch JTextAreas extrem lange Laufzeiten :-(


----------



## Marco13 (21. Jan 2011)

Mach mal einen Texteditor auf. 
Und jetzt noch einen. 
Und jetzt noch einen.
Und jetzt noch einen.
Und jetzt noch einen.
(...ungefähr 200 mal...)
Und jetzt noch einen.
Und jetzt noch einen.
Und jetzt noch einen.

Jetzt weißt du, wie Java sich da fühlt 

Mal im Ernst: Was genau willst du damit erreichen?


----------



## Doc (21. Jan 2011)

Da steht natürlich immer ein anderer Text drin. Und die Hintergrundfarbe variiert. Wenn ich den setValueAt-Befehl weglasse läuft es wunderbar. Liegt also wohl daran, oder nicht?


----------



## André Uhres (21. Jan 2011)

versuch mal in setValueAt keine Textarea zu übergeben, sondern nur die Farbe und den Text als String oder als eigene Klasse. Im Cellrenderer können wir dann den Text als Textarea mit dem gewünschten Background darstellen. Der Vorteil ist, dass dann nur eine einzige Textarea für die ganze Spalte benötigt wird.

Gruß,
André


----------



## Doc (21. Jan 2011)

Ich überlege gerade ob ich die Sache nicht zu kompliziert angegangen bin.
Es geht mir eigentlich nur darum die Hintergrundfarbe der TextPanes/TextAreas zu verändern.
Der Text bleibt immer derselbe.

Ich habe nur deswegen immer neue TextPanes mit aktualisierter Hintergrundfarbe hinzugefügt, weil ich dachte nur so könnte ich die Hintergrundfarbe der TextPanes ändern.

Kann ich auch direkt ein TextPane/TextArea einer Zelle ansprechen und den Background ändern?


----------



## KrokoDiehl (21. Jan 2011)

Moin.
Folge am besten _André Uhres_ Vorschlag: Das Tabellenmodell sollte NUR für die Daten Zuständigkeit sein und sich nicht um die Darstellung kümmern (müssen). Dafür gibt des TableCellRenderer wo man nahezu alles beliebig darstellen kann.


----------



## Doc (21. Jan 2011)

kann mir jetzt gar nicht vorstellen wie das gehen könnte :autsch:


----------



## Marco13 (21. Jan 2011)

Schau dich mal bei How to Use Tables (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components) um und frag ggf. genauer nach.


----------



## Doc (21. Jan 2011)

Die Funktionalität hab ich ja schon, es ist nur zu langsam :-(
Kann ich nicht direkt das Textpane in der Zelle ansprechen und dessen Background ändern?


----------



## SlaterB (21. Jan 2011)

dort ist keins, erst wenn gezeichnet wird, wird dort eine passende Komponente temporär verwendet,
normalerweise in JLabel


----------



## Doc (21. Jan 2011)

Danke für eure Hilfe.
Was meinst du mit "dort ist keins". Nachdem ich einmal die Tabelle mit Textpanes gefüllt habe, sind dort doch welche angelegt, oder? Nachdem diese in der Tabelle stehen, könnte ich danach darauf zugreifen und den Background ändern? Entschuldige dass ich nochmal frage, aber das war für mich jetzt etwas missverständlich.

Anstatt Textpanes könnte ich auch Labels verwenden. Wäre da die Hintergrundfarbe einfacher einzustellen?


----------



## SlaterB (21. Jan 2011)

für Entschuldigungen gibt es nie einen Grund,
TextPanes oder was auch immer ist da, wenn du sie einfügst, was aber wahrscheinlich mit ein Grund für die Langsamkeit ist und es wird versucht dir das auszureden

wenn du die TextPanes drin hast, magst du sicherlich dort was ändern können, ob das aber aber auch angezeigt wird, ist eine ganz andere Frage,
denn der Standardmechanis rechnet im Leben nicht damit, dass irgendjemand ganze TextPanes speichert,

viel sinnvoller wäre, wie schon gesagt wurde, einfache kleine Objekte mit den benötigten Daten wie Color abzulegen,
auch dann ist allerdings immer noch eine individuelle Verarbeitung nötig, damit diese Information bei der Anzeige genutzt wird
(eigenen Renderer 'installieren')

> Anstatt Textpanes könnte ich auch Labels verwenden. Wäre da die Hintergrundfarbe einfacher einzustellen? 
Label sind besser, wobei die Farbeinstellung fast gleich ist, und insgesamt immer noch 100x zu kompliziert (TextPane wäre 200x zu kompliziert  )

siehe auch
http://www.java-forum.org/awt-swing-swt/112283-jtable-zellen-farbe.html


----------



## Doc (21. Jan 2011)

Der scheint wohl dasselbe Problem zu haben.

Bin leider auch nicht mit den Renderern vertraut.

Hab noch ne kleine Frage zu JTables, und will kein neues Thema dazu aufmachen:
Wenn ich aus einer Zelle den Text aus einer Textpane/TextArea auslesen will, wie bekommm ich das hin?

Mit
table.getValueAt(i,j).toString();
bekomm ich das gesamte Objekt als String.
und
table.getValueAt(i,j).getText();
kompiliert nichtmal :-(


----------



## SlaterB (21. Jan 2011)

weil getValueAt(i,j) Object liefern, das musst du erst auf den richtigen Typ casten, falls du weißt was dieses Wort bedeutet,
Java-Grundlagen wären nützlich vor so komplizierten Dingen wie graphischen Oberflächen mit Unmengen beteiligter Klassen, Zeichenvorgängen mit Renderern usw.


----------



## Doc (21. Jan 2011)

Casten kenne ich natürlich, aber bisher nur mit ints und strings usw.

wie man ein TextPane castet weiss ich leider nicht


----------



## Marco13 (21. Jan 2011)

Ich glaube, da gibt es ein etwas grundsätzlicheres Verständnisproblem....







Dort steht: "Das ist keine Pfeife". 

Natürlich IST das keine Pfeife. Das ist ein _Bild_ von einer Pfeife.

Und eine JTable IST keine Tabelle. Das ist nur das, _womit eine Tabelle auf dem Bildschirm dargestellt wird_. 

Der Unterschied ist wirklich wichtig. Im abstraktesten Sinn IST eine "Tabelle" nur eine Ansammlung von Daten, auf die irgendwie zugegriffen werden kann. Nämlich sinngemäß in der Form 
Object daten = tabelle.gibMirDieDaten(zeile, spalte);
Zusätzlich hat so eine Tabelle noch weitere Eigenschaften und Funktionen. Insgesamt ergeben die das "geistige _Modell_ dessen, was wir als "Tabelle" bezeichnen. Und zusammengefasst ist dieses abstrakte Modell einer Tabelle im interface TableModel.

Oder kurz: Jedes "Ding", das die Funktionen anbietet, die in diesem Interface zusammengestellt sind, ist etwas, was man als "Tabelle" bezeichnen kann.

Wenn in der Tabelle sowas steht wie

```
Joe | 23 | Lesen
Tim | 45 | Schwimmen
Tom | 12 | Schreiben
Tum | 55 | Laufen
```
dann haben diese Einträge aber keine "Hintergrundfarbe", da stehen nur irgendwelche Namen und Zahlen.

Erst, wenn man diese Tabelle mit einer JTable auf den Bildschirm bringt, macht es Sinn, von Farben, Schriftarten und dem ganzen anderen Schmodder zu reden.  

Wenn du eine Tabelle erstellst, bei der die Einträge durch JLabels dargestellt werden sollen, dann heißt das nicht, dass IN der Tabelle JLabels enthalten sind. Es macht also keinen Sinn, [c]setValueAt(someLabel,r,c)[/c] aufzurufen. Es sollte immer nur [c]setValueAt(*theValueThatShouldBeDisplayedInTheLabel*,r,c)[/c] sein.

Wenn es dann um Hintergrundfarben und so geht, ist das nur eine Anweisung an die JTable, WIE sie den Inhalt des TableModels darstellen soll. Und das beschreibt man mit einen CellRenderer. 

Vielleicht noch zur Klärung: Der CellRenderer IST ein Label, aber es gibt üblicherweise für die ganze Tabelle nur EINEN CellRenderer - also nur EIN Label. Es wird immer dasSELBE Label verwendet, um die unterschiedlichen Tabelleninhalte zu zeichnen.

Also: Was soll in die Tabelle rein? Einfach nur Text? JTextAreas jedenfalls nicht...


----------



## Doc (21. Jan 2011)

Danke dir. Das hat etwas geholfen. In die Tabelle soll nur Text, das stimmt.
Ändern möchte ich nur die Hintergrundfarbe. Hab schon im Internet danach gesucht, aber irgendwie steig ich nicht ganz durch, wie ich das mit einem Cellrenderer bewerkstelligen kann.


----------



## Marco13 (21. Jan 2011)

```
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;


public class SimpleTableDemo2 extends JPanel {
    private boolean DEBUG = false;

    public SimpleTableDemo2() {
        super(new GridLayout(1,0));

        final JTable table = createTable();
        table.setDefaultRenderer(Object.class, new ColorRenderer());
        add(new JScrollPane(table));
    }

    class ColorRenderer extends DefaultTableCellRenderer
    {
        public ColorRenderer()
        {
            setOpaque(true);
        }

        public Component getTableCellRendererComponent(
                                JTable table, Object object,
                                boolean isSelected, boolean hasFocus,
                                int row, int column)
        {
            super.getTableCellRendererComponent(table, object, isSelected, hasFocus, row, column);
            if (row == 1)
            {
                setBackground(Color.RED);
            }
            else
            {
                setBackground(Color.GREEN);
            }
            return this;
        }
    }


    private JTable createTable()
    {
        String[] columnNames =
            {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};

        Object[][] data = {
            {"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)},
            {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)},
            {"Sue", "Black","Knitting", new Integer(2), new Boolean(false)},
            {"Jane", "White","Speed reading", new Integer(20), new Boolean(true)},
            {"Joe", "Brown","Pool", new Integer(10), new Boolean(false)}
        };
        return new JTable(data, columnNames);
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("SimpleTableDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        SimpleTableDemo2 newContentPane = new SimpleTableDemo2();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
```


----------



## Doc (22. Jan 2011)

EDIT:
Problem gelöst


----------

