Modifier par programmation la TableView ligne apparence
Après avoir fait un Oracle tutoriel sur la TableView, je me demandais si il y a un moyen de faire appliquer différents style CSS à l'sélectionnés TableView ligne. Par exemple, l'utilisateur sélectionne un certain ligne, clique sur le "Highlight" et la touche de ligne sélectionnée obtient fond brun, blanc de remplissage du texte, etc. J'ai lu le JavaFX tableview couleurs, La mise à jour de TableView ligne apparence et Arrière-plan avec 2 couleurs en JavaFX?, mais en vain =/
Voici la source:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
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;
public class TableViewSample extends Application {
private TableView<Person> table = new TableView<Person>();
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(600);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("lastName"));
TableColumn emailCol = new TableColumn("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("email"));
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final Button btnHighlight = new Button("Highlight selected row");
btnHighlight.setMaxWidth(Double.MAX_VALUE);
btnHighlight.setPrefHeight(30);
btnHighlight.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent e){
//this is where the CSS should be applied
}
});
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, btnHighlight);
((Group) scene.getRoot()).getChildren().addAll(vbox);
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);
}
}
}
Et la application.css à partir de laquelle le "mettre en Surbrillance la ligne sélectionnée" bouton applique la highlightedRow classe à la table sélectionnée ligne:
.highlightedRow {
-fx-background-color: brown;
-fx-background-insets: 0, 1, 2;
-fx-background: -fx-accent;
-fx-text-fill: -fx-selection-bar-text;
}
Edit:
Après plusieurs heures d'essai, la meilleure chose que je pouvais venir est cette à l'aide du code ci-dessous:
firstNameCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
@Override
public TableCell<Person, String> call(TableColumn<Person, String> personStringTableColumn) {
return new TableCell<Person, String>() {
@Override
protected void updateItem(String name, boolean empty) {
super.updateItem(name, empty);
if (!empty) {
if (name.toLowerCase().startsWith("e") || name.toLowerCase().startsWith("i")) {
getStyleClass().add("highlightedRow");
}
setText(name);
} else {
setText("empty"); //for debugging purposes
}
}
};
}
});
La partie je n'ai pas vraiment comprendre, c'est pourquoi je ne peux pas faire que de l'intérieur de la setOnAction
méthode de la btnHighlight
? J'ai aussi essayé de l'actualisation de la table par la suite (décrit ici), mais il n'a pas l'air de fonctionner. Aussi, ma "solution" ne fonctionne que pour le firstNameCol
colonne, donc, a-t-on pour définir de nouvelles cellules d'usine pour chaque colonne afin d'appliquer un certain style, ou est-il une meilleure solution?
Vous devez vous connecter pour publier un commentaire.
Si vous ne voulez pas la possibilité de réutilisation de la solution que j'ai posté ici, c'est vraiment la même chose mais à l'aide d'un anonyme intérieur de la classe pour la ligne de l'usine au lieu d'une classe autonome. Peut-être que le code est plus facile à suivre car il est tout en un seul endroit. C'est une sorte d'hybride entre Jonathan solution et la mienne, mais mettra automatiquement à jour les faits saillants, sans forcer, avec une sorte.
J'ai utilisé une liste de nombres entiers, de sorte qu'il prend en charge la sélection multiple, mais si vous n'avez pas besoin de vous, il suffit d'utiliser un IntegerProperty à la place.
Voici la ligne de l'usine:
Et voici ce que certains boutons peuvent ressembler à ceci:
Comment sur la création d'une ligne d'usine qui expose une observable liste des indices de lignes de la table qui sont à mettre en évidence? De cette façon, vous pouvez simplement mettre à jour la liste avec les indices que vous devez mettre en évidence: par exemple, en appelant la getSelectedIndices() sur le modèle de sélection et en passant à la liste de setAll(...) de la méthode.
Cela pourrait ressembler à quelque chose comme:
Maintenant vous pouvez le faire
Et votre bouton de action du gestionnaire ne
Parce que StyleChangingRowFactory enveloppements d'une autre ligne d'usine, vous pouvez toujours l'utiliser si vous avez déjà une ligne personnalisée de l'usine de mise en œuvre que vous souhaitez utiliser. Par exemple:
Ici est un exemple de code.
Voici un vilain hack solution. Tout d'abord, de définir un champ int appelé highlightedRow. Définissez ensuite une ligne d'usine sur la TableView:
Puis ajoutez le code suivant dans votre bouton sur l'action (et c'est là le vilain hack entre en jeu):
Une fois que c'est fait, vous obtenez le brun de la surbrillance sur la ligne sélectionnée. Vous pouvez bien sûr facilement prendre en charge de multiples reflets bruns en remplaçant le type int avec une liste de moustiquaires imprégnées d'insecticide.
private SimpleIntegerProperty highlightedRow = new SimpleIntegerProperty(-1)
, et puis je viens de vérifier si legetIndex() == highlightedRow.get()
et appliquer le style CSS. Qui semble fonctionner, mais encore une fois, pas jusqu'à ce que je "manuellement" actualiser le tableau par le tri.La meilleure façon que j'ai trouver pour faire ceci:
Dans mon CSS
Dans mon initialisation de la table avec un SimpleBooleanProperty d'un Objet contenu dans mon ObservableList:
Code de l'adaptation de cet exemple
J'ai peut-être trouvé quelque chose qui fonctionne:
Avec ce code ajouté, si vous appuyez sur le bouton de la ligne mise en surbrillance change de couleur lorsque vous sélectionnez une ligne différente les changements de couleur par défaut, lorsque vous appuyez sur le bouton de nouveau, elle change la couleur de la nouvelle ligne de brun.
css:
Seul problème avec cette solution est que si vous appuyez sur le bouton deux fois de suite, votre prochaine ligne sélectionnée est déjà brown. Vous devez utiliser un autre fichier css pour cela, d'autre au démarrage de l'application pas de règles css serait appliquée jusqu'à ce que vous appuyez sur le bouton.
J'ai trouvé que la meilleure solution serait d'écouter pour la ligne.itemProperty() change parce que quand vous triez par exemple les lignes de changement d'index, de sorte que les lignes d'obtenir automatiquement averti.