Ich versuche, einzelne Tabellenzellen in einem JavaFX2 TableView
zu stylen (um anzuzeigen, dass ein Tabellenzellenwert geändert wird, enthält einen Fehler, etc). Um dies zu erreichen, habe ich eine benutzerdefinierte TableCell
erstellt, die die richtige CSS-Klasse basierend auf ihrem Inhalt setzt.Wie man eine Tabellenzelle in JavaFX2 mit CSS formatiert (ohne Hover/Auswahl usw. zu entfernen)
Dies funktioniert bis zu einem gewissen Grad, aber das Problem ist, dass ich jetzt alle Effekte, den Hover, die Auswahl Farbverlauf usw. (d. H. Die Pseudoklassen) verlieren.
Wie kann ich eine Tabellenzelle mit CSS formatieren, ohne alle möglichen Kombinationen von Pseudoklassen neu definieren zu müssen?
Ich habe this answer gelesen, aber die Lösung funktioniert nicht für mich. Wenn ich -fx-control-inner-background
auf die Hintergrundfarbe setze, die ich will, bekomme ich Hover und Auswahl Farbe wie ich will, aber die anfängliche Farbe ist transparent, die offensichtlich nicht das ist, was ich will (Ich habe die Versuche in der CSS unten auskommentiert, Sie kann kommentieren und für sich selbst versuchen). Wenn Sie den Grund dafür erklären und eine Lösung anbieten können, würde ich das gerne akzeptieren.
Ich habe auch this answer gesehen, aber ich möchte wirklich keine doppelten Definitionen für alle Pseudo-Klassen erstellen (außerdem scheint es nur mit der Zeilenauswahl zu funktionieren).
Unten ist ein SSCCE, der das Problem veranschaulicht.
Screenshot (das sieht aus wie das, was ich will, mit Ausnahme der Hover und Auswahl nicht funktioniert):
TableViewSample.java (basierend auf Table View tutorial code):
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableViewSample extends Application {
public static final String CSS_ORIGINAL = "cell-renderer-original";
public static final String CSS_CHANGED = "cell-renderer-changed";
public static final String CSS_ERROR = "cell-renderer-error";
public static final String CSS_ERROR_AND_CHANGED = "cell-renderer-error-and-changed";
private TableView<Person> table = new TableView<>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Smith", "[email protected]"),
new Person("Isabella", "Johnson", "[email protected]"),
new Person("Ethan", "Williams", "[email protected]"),
new Person("Emma", "Jones", "[email protected]"),
new Person("Michael", "Brown", "[email protected]")
);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(450);
stage.setHeight(500);
Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(true);
// Cell selection only (I need this)
table.getSelectionModel().setCellSelectionEnabled(true);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
// Install custom cell renderer
emailCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
@Override public TableCell<Person, String> call(final TableColumn<Person, String> personStringTableColumn) {
return new BackgroundTableCell();
}
});
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table);
((Group) scene.getRoot()).getChildren().addAll(vbox);
scene.getStylesheets().add(getClass().getResource("/my.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}
// My custom background cell renderer
private static class BackgroundTableCell extends TableCell<Person, String> {
@Override protected void updateItem(final String item, final boolean empty) {
super.updateItem(item, empty);
setText(empty ? "" : item);
getStyleClass().removeAll(CSS_ORIGINAL, CSS_CHANGED, CSS_ERROR, CSS_ERROR_AND_CHANGED);
updateStyles(empty ? null : item);
}
private void updateStyles(String item) {
if (item == null) {
return;
}
if (item.startsWith("i") || item.startsWith("j")) {
getStyleClass().add(CSS_CHANGED);
}
else if (item.startsWith("e")) {
getStyleClass().add(CSS_ERROR);
}
else if (item.startsWith("m")) {
getStyleClass().add(CSS_ERROR_AND_CHANGED);
}
}
}
}
my.css:
.cell-renderer-changed {
-fx-background-color: rgba(255, 248, 33, .4);
/*-fx-control-inner-background: rgb(255, 248, 33);*/
-fx-accent: derive(-fx-control-inner-background, -40%);
-fx-cell-hover-color: #cce3f4;
-fx-cell-focus-inner-border: #85b9de;
}
.cell-renderer-error {
-fx-background-color: rgba(255, 159, 160, .4);
/*-fx-control-inner-background: rgb(255, 159, 160);*/
-fx-accent: derive(-fx-control-inner-background, -40%);
-fx-cell-hover-color: #cce3f4;
-fx-cell-focus-inner-border: #85b9de;
}
.cell-renderer-error-and-changed {
-fx-background-color: rgba(255, 205, 158, .4);
/*-fx-control-inner-background: rgb(255, 205, 158);*/
-fx-accent: derive(-fx-control-inner-background, -40%);
-fx-cell-hover-color: #cce3f4;
-fx-cell-focus-inner-border: #85b9de;
}
Der Grund Einstellung '-fx-control-Innen background' nicht der Fall funktioniert das' -fx-control-Innen background' als Hintergrund verwendet wird, für die Tabellenzeile, nicht für die Tabellenzelle. Die Tabellenzelle ist transparent, wenn sie nicht ausgewählt/fokussiert ist. Nicht, dass das hilft ... –
Das erklärt, warum die Antwort in der ersten verknüpften Frage nicht funktioniert. Danke! Weißt du, wie man den Zellhintergrund auch setzt? ;-) Es scheint einfach unvernünftig zu sein, etwas, das in Swing ein One-Liner war. – haraldK
Ich sehe nichts Offensichtliches. Die Hintergrundfarbe für eine Tabellenzelle wird durch '-fx-background-color: ...;' festgelegt. Im Gegensatz zu Tabellenzeilen, die eine nette Suche verwenden, können Sie den Wert für die Tabellenzelle ändern, wenn keine Pseudoklassen vorhanden sind sind gesetzt ist nur hart codiert (transparent in caspian.css und null in modena.css). Anstatt also eine Nachschlagefarbe zu ändern, müssen Sie die Einstellung direkt überschreiben, und dies scheint auch alle Pseudoklassenwerte zu überschreiben. In JavaFX 8 können Sie das Problem lösen, indem Sie die Pseudoklassen-API verwenden (anstatt Stilklassen hinzuzufügen und zu entfernen), aber ich sehe keinen 2.2 Weg, dies zu tun. –