TableView<TableView<OwnClass>>

Hallo Community,

In meinem aktuellen Projekt möchte ich eine „Shopping liste“ erstellen können.

Dazu habe ich mehrere Klassen erstellt:

Dieses Inteface ist ein Teil eines Factory patterns und ist auf die Darstellung in einer TableView ausgelegt


	//TODO add docu
	
	public SimpleStringProperty nameProperty() ;
	
	public  String getName () ;
	
	public  void setName (String s) ;

	public SimpleIntegerProperty amountProperty() ;
	
	public  int getAmount ();
	
	public  void setAmount (int i) ;
	
}```

Das hier ist Beispielhaft eine implementierende Klasse

```public class Meal implements ShoppingItem {

	private SimpleStringProperty name;
	private SimpleIntegerProperty amount;
	
	
	public Meal (String name, int amount ) {
		this.name = new SimpleStringProperty(name);
		this.amount = new SimpleIntegerProperty(amount);
	}
	
	public SimpleStringProperty nameProperty() {
		return name;
	}
	
	public final String getName () {
		return name.get();
	}
	
	public final void setName (String s) {
		name.set(s);
	}

	public SimpleIntegerProperty amountProperty() {
		return amount;
	}
	
	public final int getAmount () {
		return amount.get();
	}
	
	public final void setAmount (int i) {
		amount.set(i);
	}

}```

(also nichts besonderes...)

**Ich möchte, dass es für die beiden Klassen, die das Interface implementieren, ("Meal" und "Drink", beide haben (vorerst) die gleiche Implementierung, siehe oben) eine zweigeteilte TableView gibt**. 
Diese zweigeteilten TableViews sollen dann wiederum in einer TableView eingebettet sein. Etwa so:

_______________________________
|__________ShoppingList_________|
| Drinks ________| Meals ________|
| Name | Amount | Name | Amount |
-----------------------------------

Das Problem: Ich brauche getrennte Observable Lists, um getrennt Items in die dafür vorgesehenen Listen eintragen zu können. Wenn zB jemand ein "Meal" hinzufügt, soll es nicht als Duplikat in der "Drinks" liste stehen...


**Dazu habe ich folgendes probiert:** (auszugsweise)

```    private final static ObservableList<TableView<ShoppingItem>> data = FXCollections.observableArrayList();
    private final static ObservableList<ShoppingItem> mealData = FXCollections.observableArrayList();
    private final static ObservableList<ShoppingItem> drinkData = FXCollections.observableArrayList();

	private TableView<TableView<ShoppingItem>> table;
	
	private TableView<ShoppingItem> mealsCol;
	private TableColumn<ShoppingItem,String> mealNameCol;
	private TableColumn<ShoppingItem,Integer> mealAmountCol;
	
	private TableView<ShoppingItem> drinksCol;
	private TableColumn<ShoppingItem,String> drinkNameCol;
	private TableColumn<ShoppingItem,Integer> drinkAmountCol;

	private void addToList (ShoppingItem si) {
		
		System.out.println(si);
		
		if (si instanceof Meal)
			mealData.add(si);
		else if (si instanceof Drink)
			drinkData.add(si);
		
		System.out.println(mealData.get(0));
		
		mealsCol.setItems(mealData);
		drinksCol.setItems(drinkData);
		
		data.add(mealsCol);
		data.add(drinksCol);
		
		table.setItems(data);
	}

Die System.out.println Kommandos waren nur, um herauszufinden, ob die Objekte bis dorthin durchgekommen sind.

Ich habe schon verschiedene andere Sachen ausprobiert, jedoch ohne Erfolg; Das TableView wird nicht angezeigt.

Für eure Hilfe bedanke ich mich jetzt schon einmal recht herzlich :slight_smile:

MÜSSEN die beiden TableViews in einer weiteren TableView stecken? Das scheint das ganze recht kompliziert zu machen. Tables sind selbst im einfachsten Fall schon kompliziert genug… (wobei ich keine Ahnung von JavaFX habe, aber DAS weiß ich ;-))

EDIT: Nochmal zur Klärung: Wenn das wirklich so sein sollte (was ich nicht glaube), dann KÖNNTE man eine Tabelle aus Tabellen machen:


|-----------------------------------|
|              Shopping             |
|-----------------------------------|
|    Meals        |       Drinks    |
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|    Meals        |       Drinks    |  <--- Das macht... 
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|    Meals        |       Drinks    |  ... doch keinen Sinn!? 
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|

Prinzipiell kann man sowas mit FX schon machen.

Ich werde aber nicht das Tutorial hier abschreiben:
Using JavaFX UI Controls: Table View | JavaFX 2 Tutorials and Documentation

bye
TT

@Timothy_Truckle : Falls du auf Figure 12-3 anspielst: Das dachte ich zuerst auch. Aber der Beschreibung nach soll das hier ja wirklich eine ECHTE Tabelle sein, wo jede Zelle (!) wieder eine ECHTE Tabelle ist…

Hey Leute,

danke erst mal für die Antworten.

Ihr habt Recht, ich habe da einen Denkfehler drin gehabt. Also noch mal (korrigiert), es soll nachher so aussehen:

Das war schon eine richtige Ansicht:

|-----------------------------------|
|              Shopping             |
|-----------------------------------|
|    Meals        |       Drinks    |
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|

ABER:

Wenn ich addDrink (vodka, 20) [Russenhochzeit :D] eingebe, dann soll so etwas rauskommen:

|-----------------------------------|
|              Shopping             |
|-----------------------------------|
|    Meals        |       Drinks    |
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
|        |        | Vodka  |   20   |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|

In dem Tutorial wird allerdings nur so etwas beschrieben:

|-----------------------------------|
|              Shopping             |
|-----------------------------------|
|    Meals        |       Drinks    |
|-----------------|-----------------|
| name   | amount |  name  | amount |   
|--------|--------|--------|--------|
| Vodka  |   20   | Vodka  |   20   |
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|

Und an dieser Stelle bin ich verzweifelt. Ich ging davon aus, dass wenn ich zwei separate Listen brauche, ich auch separate TableViews haben muss. Daher die Idee, dasss “Shopping” eine TableView ist, Die wiederrum 2 TableViews beinhaltet, die je eine eigene ObservableList haben. Dann könnte ich eigene Einträge für jede Liste machen. (So jedenfalls meine Idee…)

Könnt ihr mir sagen, wie ich so etwas realisieren kann?

Und genau das ist schwierig. Nochmal: Das würde bedeuten, dass nicht einfach nur zwei Spalten in der „Shopping“-Tabelle sind (Drinks und Meals, jeweilst wieder eine eigene Tabelle), sondern dass diese Shopping-Tabelle auch merhere ZEILEN enthalten könnte, wo jede Zeile wieder zwei Spalten enthält.
(Das geht sicher auch, aber würde absurd kompliziert und aufwändig werden)

Eigentlich klingt es viel mehr so, als sollte es schlicht zwei Tabellen nebeneinander geben. Meals und Drinks. Dass die eine gemeinsame „Übschrift“ haben sollen (nämlich „Shopping“) ist dann das wenigste.

EDIT: Es gäbe noch einen vergleichsweise einfachen, aber sehr häßlichen „Workaround“, um das hier


|-----------------------------------|
|              Shopping             |
|-----------------------------------|
|    Meals        |       Drinks    |
|-----------------|-----------------|
| name   | amount |  name  | amount |  
|--------|--------|--------|--------|
|        |        |        |        |
|--------|--------|--------|--------|

wirklich als EINE Tabelle zu erstellen, und trotzdem die Einträge getrennt zu verwalten: Eine Klasse „DrinkAndMeal“, die NUR dem Zweck dient, eine Zeile dieser (sehr speziellen) Tabelle zu modellieren - aber :sick: zwei getrennte Tabellen, einfach nebeneinander, mit einem Label „Shopping“ als gemeinsame Überschrift, sollte doch eigentlich seinen Zweck erfüllen…!?

Hmm, da hast du eigentlich recht, ‘warum einfach wenn es auch kompliziert geht?’ :lol:

Danke Marco! ich werde das dann auch so machen, in dem Stil:

zwei getrennte tableviews, die ich in einer VBox zusammenhefte

Dankschön

falls man gemeinsam scrollen wollte ist eine Tabelle schon ziemlich nett,

JTable mit TableModel in Swing ist dazu mächtig, die getValueAt()-Methode kann beliebig suchen oder gar neu berechnen, was in eine Zelle hinein soll,
es braucht nicht einmal Daten im Hintergrund, die getRowCount()-Methode kann auch 100.000 oder beliebiges voraussagen, ohne dass diese Daten existieren müssen

überschaubar einfach ist es dort dann natürlich auch, zwei Listen mit 6 und 9 Elementen vorzuhalten, bis Index 5 jeweils das einfache Element einer dieser Listen zu geben,
bei Index 6 für eine Column null oder Leerstring, für die andere noch das vorhandene Element usw.,
einen Automatismus ‚mach mal diese beiden Datenmengen zusammen‘ kenne ich dort auch nicht, aber manuell quasi alles möglich

auch mit setValueAt() zurückzurechnen

Selektion von Zellen auch genau genug um sinnvoll damit was anfangen zu können

JavaFX TableView scheint nicht in diese Richtung zu gehen:
java - How to set and get the cell value of JavaFX Table like swing JTable - Stack Overflow


meinen schon eingetippten Absatz zu DoubleShoppingItem kann ich mir ja nun sparen :wink:

Das mit dem Scrollen ist ein Punkt. Bei JavaFX (womit ich, um das zu betonen, bisher nicht wirklich was gemacht habe) scheinen aber die Automatismen (vermutlich wegen der Observable-Collections) noch etwas weiter zu gehen. Sicher könnte man das auch in EINER Table unterbringen, und analog zur JTable die passenden Werte für die Zellen rausholen (ggf. aus zwei getrennten Listen), aber auch das würde deutlich mehr “Eigenarbeit”/Individualisierung der Table bedeuten, als schlicht zwei Tabellen nebeneinander…

Ich denke auch das zwei Tableviews eine gute Entscheidung ist.
Das in einer VBox zusammenzufassen, naja?

Was einen einige Jahre als Softwareentwickler lehren ist, dass es immer mit einer Tabelle anfängt in der es nur zwei Spalten geben soll. Eine Bezeichnung und eine Zahl. Und kaum passt das und das Layout stimmt usw. usf. kommen 10 Spalten dazu.

In einer Shoppingliste braucht es immer noch eine Checkbox oder zumindest ein X für erledigt und im Einkaufswagen.
Dann kommen Preise hinzu, Einzelpreis, Gesamtpreis, EK, VK, Steuern.
Eine Spalte für Bezahlt, auf Rechnung, Kommi.
Dann evtl. noch das Datum, wann zur Liste hinzugefügt und von wem, sowie Bestelldatum, Lieferdatum, etc.
Irgendwann will man noch Bemerkungen hinzufügen und anzeigen.

Kurzum so Listen, auch wenn hier nur ein Teil davon zutreffen sollte haben die Tendenz in die Breite zu gehen und da wird es mit einer VBox recht bald sehr eng.

Aber zwei Tabellen kann man auch z.B. auf zwei Tabs verteilen oder man macht alles untereinander in eine Tabelle und baut dann einen Filter hinzu um sich nur das eine oder das andere oder alles zusammen anzeigen zu lassen.

Ausser man ist ein Berliner Startup, nennt sich 6 Wunderkinder, baut Wunderlist, eine Listenanwendung mit nur einer Checkbox und Bezeichnung um dies dann für hundert Millionen an Microsoft zu verkaufen.

Aber den genauen Anwendungsfall und das Umfeld wo das genutzt werden soll kenne ich nicht, dass zwei Spalten reichen bezweifle ich aber.

(Nochmal der disclaimer:
← Der da hat keine Ahnung von JavaFX :smiley:
aber…)

Sollte man nicht ggf. einfach die „Vbox (mit den beiden Tabellen drin)“ in EINE „Scrollpane“ stecken können?

Also zuerst mal eine Frage ob die Tables nebeneinander sein sollen oder nicht? Falls ja wäre ne VBox glaub ich suboptimal, denn V -> Vertikal -> Unter/Übereinander ;D
Das führt uns damit zur HBox, was aber eig das gleiche ist (bis auf die Ausrichtung eben).

Was V/HBox und Scrollpane angeht muss ich sagen, hab ich die Erfahrung gemacht, dass man vorher gut wissen sollte wie groß die Box denn vom Grundauf sein soll.
Wenn ich sowas benutzt habe (z.b. Userliste mittels VBox und Scrollpane) hat sich die Breite nicht mehr verändert (auch wenn man Eingestellt hat, dass kein horizontaler Scrollbalken gewünscht ist [Vllt hab ich auch nur zu schnell immer aufgegeben^^]).

Was mich jetzt noch am geposteten Code etwas stört, ist das immer wenn ein neues Item hinzugefügt wird, immer neu “setItems” aufgerufen wird. Sollte eigentlich unnötig sein, da die Listen ja Observable sind und die TableView’s automatisch sich aktualisieren sollte, sobald was eingefügt/gelöscht wird

MFG
Clayn