# JTable darstellen von leeren Zellen



## redbomber (20. Jan 2009)

Hi zusammen, ich brauche mal wieder eure Hilfe.

Ich besitze eine LinkedList<Probe> von Objekten (Probe), die ich in einer JTable darstelle.
Jede Probe befindet sich in einer Zelle.
Die Proben beistzen Positionen (sind nach diesen auch sortiert).
Anhand der Positionen werden die Proben auf die Zellen aufgeteilt.

Bisher stelle ich alle Proben direkt aufeinander in den Zellen dar. Nun gibt es aber zwischen zwei Proben auch Lücken.

Z.B: probe03 an Position 1007
       probe04 an Position 1012

Nun möchte ich die Lücken in der Tabelle auch noch darstellen, also befinden sich dann zwischen Zellen von probe03 und probe04 view "leere" Zellen (Zellen in denen sich keine Proben befinden).



Ich weiss zu Beginn wieviele Zellen es ingesamt gibt, also weiss dann auch wieviele mit Proben gefüllt sind und wieviele leer sind. 


Wie aber befülle ich die Tabelle?
Normal hole ich mir das Objekt wie folgt im TableModel implementiert:


```
public Object getValueAt(int row, int col) {
       Object object = null;

	int indexOfProbe = -1;
        // Hier berechne ich den Index der Probe. Einfach zählen um die wievielte Zelle es sich handelt.
	indexOfProbe = tableManager.getProbeId(row, col);

	Probe probe = tableManager.getProbe(indexOfProbe); //hier greif ich auf die LinkedList<Probe> zu
	object = pb.getValue();

	} 
// Entweder gebe ich den Wert zurück, wenn sich in der Zelle ein Objekt befindet, oder ich gebe "-" zurück
return (object == null) ? "-" : object;
}
```

Diese Implementierung funktioniert aber nur, wenn ich alle Zellen direkt nacheinander befülle, ich darf also keine "leere" Zellen zwischendrin besitzen.


Möchte ich das ganze auch mit den "leeren" Zellen dazwischen realisieren, müsste ich ja einfach ebenfalls "-" zurückgeben. 

Also bisher muss ich ja einfach zählen in der wievielten Zelle ich bin, dann hab ich den Index der Probe von der ich den Wert holen kann.
Aber mit den "leeren" Zellen geht das dann ja nicht mehr so.

Habt ihr mir eine Idee?


----------



## redbomber (20. Jan 2009)

Ich könnte mir einen int[] erzeugen.

Wenn getValueAt() aufgerufen wird, dann berechne ich die Position in dem Array.
ist der Wert <0 weiss ich dass es sich um eine Lücke handelt.
ist der Wert >0, dann handelt es sich um den INdex der Probe, mit dem ich wiederum die Probe aus der LinkedList<Probe> heraushole.

Ich müsste bei der Initialisierung einmal diesen Array erzeugen. Allerdings kann der Array gut 1.000.000 Zellen enthalten. Ob das dann noch schnell genug ist? Und der Array belegt ja wieder eine Menge an Speicher.
Was meint ihr, ist das ein sinnvoller Ansatz?


----------



## hdi (21. Jan 2009)

Nein :bae: 

(Ich bin leider grad beschäftigt, dir wird hier sicherlich gleich jemand helfen, aber so ein riesen
Array kannst du sofort ausschließen)


----------



## Ebenius (21. Jan 2009)

Du meinst, da können Lücken sein. Wie kommt es zu solchen Lücken? Soll ein Nutzer "Hier Lücke einfügen" klicken? Oder gibt es eine Regel "alle 24h 10 neue Lücken zufällig verteilen"? Oder ergibt sich das aus den Proben, in etwa "zwischen Proben die mit 'A' anfangen und Proben die mit 'B' anfangen gibt's immer eine Lücke"? Oder, oder, oder...

Davon hängt natürlich maßgeblich die Herangehensweise ab.

[ edit ] Darauf wollte ich ja vorhin schon hinweisen: Eine LinkedList ist genau die falsche Listen-Implementation, um mit einem Index darauf zuzugreifen. Du willst eine Million Zeilen, dann heißt das, das 500.000te Element bekommst Du mit _list.get(500000);_ durch 499.999maliges Vorwärtslaufen. Nich so gut. Wie wäre denn eine ArrayList?


----------



## redbomber (21. Jan 2009)

Also das ganze wird eine Erweiterung einer bestehenden Software.
Die Daten werden von der Software gesammelt und ich erhalte diese als LinkedList<Probe>. Intern kann ich diese natürlich in einem anderen Datentyp intern speichern.


Die JTable kann man sich bei mir wie eine Karte vorstellen. Jede einzelne Zelle ist ein Teil dieser Karte.
An vielen Positionen besitzte ich Informationen, an diesen werden dann die Proben dargestellt (Zelle bekommt spezielle Farbe). An aber noch viel mehr Positionen besitze ich einfach keine Informationen. Diese Zellen möchte ich dann zb. weiss machen.

Wenn ich jetzt die Tabelle aufbaue, muss ich ja für jede Zelle wissen ob ich da eine Information besitze -> dann die passende Probe suchen und darstellen.
Oder ob die Zelle ohne Information ist -> also einfach weiss lassen.

Die Zellen ohne Informationen machen bestimmt 2/3 der Zellen aus (diese müssen aber angezeigt werden)


----------



## Ebenius (21. Jan 2009)

Sollte dann nicht Dein TableManager wissen, wo sich die noch nicht probierten Zellen befinden? An diesen Stellen sollte er dann null zurückliefern.


----------



## redbomber (21. Jan 2009)

also du meinst mein TableModel?
Ja genau, die Methode 
	
	
	
	





```
public Object getValueAt(int row, int col)
```
 ruft er ja für jede Zelle auf.
Aber in dieser Methode muss ich ja irgendwie wissen auf welche Daten ich zugreifen muss.


----------



## Ebenius (21. Jan 2009)

Anonymous hat gesagt.:
			
		

> also du meinst mein TableModel?



Nö. Ich meine den TableManager... Oder was auch immer das für eine Klasse ist, die diese Zugriffe bedient: 
	
	
	
	





```
indexOfProbe = tableManager.getProbeId(row, col); 

Probe probe = tableManager.getProbe(indexOfProbe); //hier greif ich auf die LinkedList<Probe> zu 
object = pb.getValue();
```

Ebenius


----------



## redbomber (21. Jan 2009)

hmm,
also das macht bei mir das TableModel. Dieses legt die Anzahl der Spalten und Zeilen der Tabelle fest und liest die Werte aus den Zellen aus.
Wenn ich mir eine Tabelle anzeigen lassen möchte, dann ruft das TableModel für jede Zelle die getValueAt(row,col) Methode auf.


----------



## redbomber (21. Jan 2009)

AHSO!!!
Sorry!
Ja also hinter dem tableManager versteckt sich nur eine weitere Klasse, welche spezielle Methoden anbietet.


```
indexOfProbe = tableManager.getProbeId(row, col);
```
liefert mir für die row/col den index der Probe für die aktuelle Zelle.
-> hier berechne ich aber nur in der wievielten Zelle ich gerade bin, damit ich somit den Index erhalte.


```
tableManager.getProbe(indexOfProbe)
```
liefert mir dann für diesen Index die Probe

Hab diese Funktionen in meinen tableManager verpackt, da ich die auch an anderer Stelle brauche.


----------



## Ebenius (21. Jan 2009)

Naja, aber dann sollte der TableManager doch das Wissen haben, welche Zelle keine Probe hat, oder?


----------



## redbomber (22. Jan 2009)

also meinen TableManager können wir eigentlich ignorieren.
Meine Tabelle hat einen speziellen Aufbau, zb. ist die erste Spalte nicht mit Werten belegt, ist sowas wie eine Legende.
Weiter habe ich immer wieder eine Zeile von Zellen als Platzhalter eingefügt (muss so sein)
Also macht mein Table Manager nichts anderes als aus (row,col) die ganzen Platzhalterzellen abzuziehen.
-------------------------------------------------------------------------------------------------------------------------------------------
*
Vielleicht kann ich dir kurz meinen neuen Ansatz vorstellen:*
Zu beginn beitzte ich eine LinkedList<Probe> die ich auf die Tabelle anhand der Positionen der Proben verteilen muss.

Mit einer HashMap<Position,Probe> kann ich so etwas realisieren. DIese HashMap muss ich zu beginn einmal initialisieren.

Wenn nun das TableModel Werte aus den Zellen ausliesst, muss ich einfach nur prüfen ob bei der eben betrachtete Zelle (z.B. Zelle nummer 128) für die Position 128 ein eintrag in der HashMap vorliegt.

Falls ja, dann wird die Zelle farblich dargestellt, falls nein, dann hab ich eine weisse Zelle.


Das funktioniert soweit!


Aber:
- Wie schnell wird das ganze werden wenn ich z.b. 200.000 Einträge in der Zelle habe?
- Was mache ich, wenn eine Probe nicht nur 1 Position groß ist, sondern z.B. 10 Positionen lang?


----------



## redbomber (22. Jan 2009)

Also der Ansatz mit der Heatmap geht sogar.
Ebenfalls wenn bei mir eine Probe in mehreren Zellen vorkommt.
Als Key verwende ich dabei immer die Position der Probe und der Value ist dann die Probe.


Das befüllen der HeatMap bei der Initialisierung dauert allerdings etwa eine Minute, bei 220.000 Proben.
Und den Arbeitsspeicher, den ich der JVM zur Verfügung gestellt habe, knickt von 1400 MB auf 300 MB ein.


----------

