JavaFX TableView - nicht ausgewählte Reihe ansprechen

Raikbit

Mitglied
Hi, ich habe wie im Titel beschrieben das Problem, dass ich nicht weiß wie ich in einem TableView ein nicht selektiertes Element anspreche.

Also was ich machen möchte:

ich habe eine Tabelle mit Einträgen in 3 Spalten und n-Zeilen. Nun möchte ich Zeile n auslesen ohne sie auswählen zu müssen und wenn meine Bedingung erfüllt ist Zeile n grün einfärben (Hintergrundfarbe).

________________________________________________________________________________

finde leide überall nur die Fälle ändern wenn ausgewählt ...

:rtfm:
 
Nun ja, deine Daten sind ja alle in der Items-Liste deiner TableView, daher musst du also einen deiner TableCell-Implementierungen heranziehen, um hier die Änderung zu machen.
Z.B. scheint hier jemand etwas zu machen, das dir helfen könnte:
java - JavaFX tableview colors - Stack Overflow

Du musst also irgend etwas á la dem folgendem machen:

(z.B. im initialize deines Controllers:
Java:
	@Override
	public void initialize(URL location, ResourceBundle resources) {

		// [...]

Callback<TableColumn.CellDataFeatures<Device, Device>, ObservableValue<Device>> contentCallback = new Callback<TableColumn.CellDataFeatures<Device, Device>, ObservableValue<Device>>() {
			@Override
			public ObservableValue<Device> call(CellDataFeatures<Device, Device> param) {
				return new SimpleObjectProperty<Device>(param.getValue()); // dein Objekt per Zeile
			}
		};
		
		tableColumnDetected.setCellValueFactory(contentCallback);
		tableColumnDetected.setCellFactory(new Callback<TableColumn<Device, Device>, TableCell<Device, Device>>() {
			@Override
			public TableCell<Device, Device> call(TableColumn<Device, Device> param) {
				return new DeviceDetectedTableCell(); // dein Tabellen-Zelle
			}
		});

		// [...]

	}

	/*
	 * [...] weitere Klassen/Methoden/Whatever
	 */

	public class DeviceDetectedTableCell extends TableCell<Device, Device> {
		
		public DeviceDetectedTableCell() {}
		
		@Override
		protected void updateItem(Device item, boolean empty) {
			
			super.updateItem(item, empty);
			
			if (empty) {
				textProperty().unbind();
				setText(null);
				graphicProperty().unbind();
				setGraphic(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				// an bestimmten Zustand deiner Datenzeile oder irgend einen anderen Trigger binden
				textProperty().bind(new DeviceDetectedStringBinding(item));
				graphicProperty().bind(new DeviceDetectedBinding(item));
				setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			}
			// oder wie im StackOverflow-Post beschrieben hier direkt die Farben setzen
			// mit einem Binding aber bist du flexibler - du musst da ja nix besonderes machen, sondern kannst da ja 
			// statt wie ich das item, die TableRow übergeben und dann die "priority" setzen
		}
	}

Ist die Kombination aus StackOverflow und meinem geistigen Erguss halbwegs klar? Ich verstehe mich ja total ;-)
 
hmm nich so richtig ... hatte die Seite von Stack auch schon offen...

also ich mach mal nen Beispielpseudocode rein:

Code:
protected void markRow() {
		for (int i = 0; i < Eintraege.size(); i++) {
			if (Eintag n erfüllt Bedingung) {
				if (Table.getItems().get(i).getSpalte1().equals(Bedingung1())
						&& Table.getItems().get(i).getSpalte2().equals(Bedingung2())) {

					System.out.println("jetzt einfärben");
					ownTaskCardTable.getRow(i).set(BackgroundcolorGreen);

				}
			}
		}
	}

also ich weiß halt nicht wie ich an die Row komme und diese dann einfärbe. Die for und if funkionieren.
 
Das geht nicht ganz so einfach, glaube ich. Du hast aber von innerhalb der TableCell Zugriff darauf, daher meine ich, dass es dort die richtige Stelle ist und das zeigte die StackOverflow-Frage.

Dein Model sollte vielleicht ein weiteres Feld - einen Indikator irgendeiner Art - enthalten (den musste ja nicht abspeichern, der muss nur zur Laufzeit da sein), dann könnte deine Pseudo-Code-Methode eben diesen Indicator manipulieren.

Ich habe es jetzt eine Weile probiert, weil ich schon ein paar mehr Hinweise liefern wollte, muss aber zugeben, dass das wirklich nicht so recht klappt. Jedenfalls bei mir unter Java7u45... Vielleicht solltest du die Frage noch mal auf StackOverflow und/oder einem JavaFX-orientierten Forum von Oracle stellen.
Ich komme damit leider auch nicht weiter und hab dann doch noch ein paar andere Dinge zu tun.

Sorry!
 
Heureka!

Eine Kombination aus meinem bisherigen Ansatz, dem von StackOverflow und dem hier
https://gist.github.com/jewelsea/5470095
hat mir weitergeholfen.

Ich hab bei mir bereits ein Binding in meiner TableCell für den Graphics-Node auf eine BooleanProperty meines Models:

Java:
	public class DeviceDetectedTableCell extends TableCell<Device, Device> {
		
		public DeviceDetectedTableCell() {}
		
		@Override
		protected void updateItem(Device item, boolean empty) {
			
			super.updateItem(item, empty);

			if (empty) {
				textProperty().unbind();
				setText(null);
				graphicProperty().unbind();
				setGraphic(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				textProperty().bind(new DeviceDetectedStringBinding(item));
				graphicProperty().bind(new DeviceDetectedBinding(item));
				setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			}
		}
	}

Erster Schritt: CSS anpassen
HTML:
.highlight {
  -fx-control-inner-background: skyblue;
  -fx-accent: derive(-fx-control-inner-background, -40%);
  -fx-cell-hover-color: derive(-fx-control-inner-background, -20%);
}

Zweiter Schritt: Styleclass in der Zelle
Java:
	public class DeviceDetectedTableCell extends TableCell<Device, Device> {
		
		public DeviceDetectedTableCell() {}
		
		@Override
		protected void updateItem(Device item, boolean empty) {
			
			super.updateItem(item, empty);
			getTableRow().getStyleClass().remove("highlight");
			if (empty) {
				textProperty().unbind();
				setText(null);
				graphicProperty().unbind();
				setGraphic(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				textProperty().bind(new DeviceDetectedStringBinding(item));
				graphicProperty().bind(new DeviceDetectedBinding(item, this));
				setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			}
		}
	}

Dritter Schritt: Anpassen des DeviceDetectedBindings
Java:
	private final class DeviceDetectedBinding extends ObjectBinding<Node> {
		
		private final Device device;
		private final TableCell<Device, Device> cell;
		
		public DeviceDetectedBinding(final Device device, final TableCell<Device, Device> cell) {
			this.device = device;
			this.cell = cell;
			super.bind(device.detected());
			super.bind(device.licensed());
		}
		
		@Override
		protected Node computeValue() {
			ImageView iv = null;
			if (device.isDetected()) {
				if (device.isLicensed()) {
					iv = ImageResource.getImageView("fugue/tick-circle.png");
				} else {
					iv = ImageResource.getImageView("fugue/skull.png");
				}
				cell.getTableRow().getStyleClass().add("highlight");
			} else {
				iv = ImageResource.getImageView("fugue/cross-circle.png");
				cell.getTableRow().getStyleClass().remove("highlight");
			}
			return iv;
		}
	}
Hier kam jetzt die TableCell in den Konstruktor und die beiden Styleclass-Sachen hinzu.

Du kannst hier einfach faken, indem du entweder in der Zelle einfach nur
Code:
setContentDisplay(ContentDisplay.TEXT_ONLY);
machst, oder als Node einfach null zurück gibst.

Wenn mich nicht alles täuscht, kann man dann nur noch sagen: Simsalabim! Und fertig ist der Lack!

Viel Erfolg!

PS: Wie gesagt, der obere Teil meiner Aussage aus dem letzten Post bleibt bestehen. Du musst schon einen Indicator (eine Property!) haben und deine markRow-Methode muss hier nur den Indicator anpassen, der Rest geschiet über das Binding!
 
Das Thema wurde beendet... Ich gehe davon aus, dass es geklappt hat? Etwas Feedback wäre im Forum durchaus willkommen.
 

Zurück
Oben