45 votes

ListView avec personnalisé CellFactory garnitures invisible nœuds

Mon problème de mise en page

J'ai un petit problème avec l' ListView et je ne sais pas si c'est à cause de certaines connaissances que j'ai manquant ou si mon approche est erronée. Dois admettre que je ne suis pas encore clair comment JavaFX gérer la mise en page dans le nombre de cas possibles.

ListView trims my attempt at layout

La capture ci-dessus montre le résultat je reçois deux fois avec le même code, sauf que sur le second, une forme invisible - je utiliser pour la cohérence de mise en page est visible pour le débogage.

Les différentes classes concernées par l' CellFactory étendre Group, j'ai essayé avec quelques autres Parent sans beaucoup de succès jusqu'à présent.


Comment reproduire

Plutôt que de partager mon StarShape, StarRow et certains autres misc classes (j'en serais heureuse si demandé), j'ai écrit un échantillon de reproduire le problème. La classe s'étend Application et remplace l' start(...) méthode en tant que telle:

@Override
public void start(Stage primaryStage) throws Exception {
    final StackPane root = new StackPane();
    final Scene scene = new Scene(root, 400, 600);

    final ListView<Boolean> listView = new ListView<>();
    listView.setCellFactory(this::cellFactory);

    for (int i = 0; i < 5 ; i++) {
        listView.getItems().add(true);
        listView.getItems().add(false);
    }

    root.getChildren().add(listView);

    primaryStage.setScene(scene);
    primaryStage.setTitle("ListView trims the invisible");
    primaryStage.show();
}

this::cellFactory est

private ListCell<Boolean> cellFactory(ListView<Boolean> listView) {
    return new ListCell<Boolean>() {
        @Override
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                setText(null);
            } else {
                final Rectangle tabShape = new Rectangle();
                tabShape.setHeight(20);
                tabShape.setWidth(40);
                tabShape.setVisible(item);

                final Label label = new Label(item.toString());
                label.setLayoutX(40);

                final Group cellRoot = new Group();
                cellRoot.getChildren().add(tabShape);
                cellRoot.getChildren().add(label);

                setGraphic(cellRoot);
            }
        }
    };
}

Le ci-dessus va afficher un ListView<Boolean> avec des formes noires en face de l' true articles (en raison de l' tabShape.setVisible(item); bits). L' false des articles sont à la recherche comme réguliers Label objets comme si l'invisible forme dans leur Group n'était pas là (mais c'est).


Commentaires de clôture

Débogage de cela, il s'avère groupes avec l'invisible formes sont données négatives layoutX les valeurs de propriété. Ainsi, Label contrôles ne sont pas alignés, comme je voudrais qu'ils soient. Il ne se produit pas quand je l'appelle setLayoutX et setLayoutY à l'extérieur d'un ListView (l'invisible formes ne force les décalages), mais ce n'est probablement pas le seul endroit où il allait se passer.

Ce qui se passe et comment l'éviter? Sinon, comme je devine que je suis en approche de ce mal, ce serait de la bonne façon? En d'autres termes, quelle est la question que je doit demander au lieu de cela?

13voto

Robby Cornelissen Points 11222

En prenant de l' @dlatikay commentaire, au lieu de définir l'espace réservé éléments de l'invisible, vous pouvez vous rendre transparent en définissant leur opacité 0.0.

Appliqué à la MCVE de votre question, ce serait fait en remplaçant:

tabShape.setVisible(item);

avec:

tabShape.setOpacity(item ? 1.0 : 0.0);

En termes d'expérience utilisateur, vous pouvez aller une étape plus loin. Au lieu de définir le "inactif" étoiles entièrement transparent, vous pouvez les configurer pour être quasi-transparent, comme dans cette maquette (avec une opacité de 0.1):

mockup

Les avantages que je vois sont:

  1. Il indique non seulement la notation d'un élément dans la liste, mais également la note maximale.
  2. Il évite maladroit des espaces vides pour les éléments de liste avec zéro étoiles.

4voto

Michael Points 20266

Je devine que je suis en approche de ce mal

Non, vous n'êtes pas. Comme avec tous les modèles, il y a souvent plusieurs façons d'aborder le même problème. Votre approche est vraiment bon, et vous êtes très proche d'une solution de travail.

Vous pouvez réaliser ce que vous êtes après, avec un simple 1 changement de ligne. C'est, en changeant l' Group d'un HBox.

Un HBox s'assure que les éléments sont ordonnés à l'horizontale, l'un après l'autre. Ils permettent aussi à des éléments invisibles à toujours prendre de la place.

J'ai aussi commenté une ligne: label.setLayoutX(40). J'ai fait cela car HBox ne respectent pas ce paramètre, et de fait, vous n'avez pas besoin. Il changera automatiquement les éléments horizontalement par autant est nécessaire.

@Override
protected void updateItem(Boolean item, boolean empty) {
    super.updateItem(item, empty);

    if (empty || item == null) {
        setText(null);
    }
    else {
        final Rectangle tabShape = new Rectangle();
        tabShape.setHeight(20);
        tabShape.setWidth(40);
        tabShape.setVisible(item);

        final Label label = new Label(item.toString());
        //label.setLayoutX(40);

        final HBox cellRoot = new HBox();
        cellRoot.getChildren().add(tabShape);
        cellRoot.getChildren().add(label);

        setGraphic(cellRoot);
    }
}

Quand je fais ces changements, votre mise en page sera rendu comme suit:

enter image description here


Important: Votre exemple et vos captures d'écran sont légèrement différentes. Vous souhaiterez peut-être utiliser un VBox pour votre star de l'exemple (V 'vertical', H "horizontale").

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X