JavaFX CSS ne fonctionne pas lors de l'utilisation de fx: factory pour remplir le composant GridPane personnalisé


J'ai un problème avec CSS sur le composant lorsque fx:factory est utilisé, de plus la propriété gridLinesVisible ne semble pas fonctionner non plus. Permettez-moi d'aller au point, mon composant ressemble à ceci:

<?import javafx.scene.layout.GridPane?>
<fx:root type="javafx.scene.layout.GridPane" xmlns="http://javafx.com/javafx/8"
         xmlns:fx="http://javafx.com/fxml/1" maxWidth="400.0" prefWidth="220.0"
         stylesheets="@custom.css" styleClass="grid" gridLinesVisible="true">
</fx:root>

Et je l'utilise comme ceci:

<MyCustomView fx:id="myCustomView" prefHeight="240.0" rotate="-90" alignment="CENTER"
                    fx:factory="createMyCustomView"/>

Et le code de la méthode ressemble à ceci:

public static MyCustomView createMyCustomView() {
    ObservableList<RowView> rowViews = FXCollections.observableArrayList();
    for (int i = 0; i < 20; i++) {
        RowView rv = new RowView();
        rv.setRow(i);
        rowViews.add(rv);
    }
    MyCustomView view = new MyCustomView();
    view.setRows(rowviews);
    return view;
}

J'ai essayé de configurer les feuilles de style et la classe de style dans le constructeur, la méthode d'usine, le contrôleur et FXML et rien ne fonctionne. Mais quand je supprime l'appel fx:factory="createMyCustomView" CSS et gridLinesVisible propriété travail. Je n'ai pas d'autres idées à essayer.

Bravo, Rafal

MODIFIER

J'ai légèrement modifié le projet; voici my_custom_view.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.collections.FXCollections?>
<?import sample.RowView?>
<fx:root type="sample.MyCustomView" xmlns="http://javafx.com/javafx/8"
         xmlns:fx="http://javafx.com/fxml/1" maxWidth="400.0" prefWidth="250.0"
         stylesheets="@custom.css" styleClass="grid" gridLinesVisible="true">
    <rows>
        <!--If using views defined inside the view gridlines and css work-->
        <FXCollections fx:factory="observableArrayList">
            <RowView row="1"/>
            <RowView row="2"/>
            <RowView row="3"/>
            <RowView row="4"/>
            <RowView row="5"/>
            <RowView row="6"/>
            <RowView row="7"/>
            <RowView row="8"/>
        </FXCollections>
    </rows>
</fx:root>

Voici la classe MyCustomView:

package sample;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;

import java.io.IOException;
import java.lang.ref.WeakReference;

    public class MyCustomView extends GridPane {

        private static final String FXML_RESOURCE_PATH = "my_custom_view.fxml";

        public MyCustomView() {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(FXML_RESOURCE_PATH));
            fxmlLoader.setRoot(this);
            fxmlLoader.setController(this);

            try {
                fxmlLoader.load();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        private void insertRowsAndLabels() {
            this.getChildren().clear();
            if (rows.get() != null) {
                for (RowView rv : rows.get()) {
                    Label label = new Label(String.valueOf(rv.getRow()));
                    Group group = new Group(label);
                    group.setRotate(90);
                    this.add(group, 1, rv.getRow());
                    this.add(rv, 0, rv.getRow());
                }
            }
        }

        public final ObjectProperty<ObservableList<RowView>> rowsProperty() {
            return rows;
        }

        private ObjectProperty<ObservableList<RowView>> rows =
                new SimpleObjectProperty<ObservableList<RowView>>(this, "rows") {

                    WeakReference<ObservableList<RowView>> oldItemsRef;

                    @Override
                    protected void invalidated() {
                        final ObservableList<RowView> oldItems = oldItemsRef == null ? null : oldItemsRef.get();
                        final ObservableList<RowView> newItems = getRows();

                        // Fix for RT-36425
                        if (newItems != null && newItems == oldItems) {
                            return;
                        }

                        oldItemsRef = new WeakReference<>(newItems);
                    }
                };

        public final void setRows(ObservableList<RowView> value) {
            rowsProperty().set(value);
            insertRowsAndLabels();
        }

        public final ObservableList<RowView> getRows() {
            return rows.get();
        }

        public final BooleanProperty autoFillProperty() {
            if (autoFill == null) {
                autoFill = new SimpleBooleanProperty(this, "autoFill", false);
            }
            return autoFill;
        }

        private BooleanProperty autoFill;

        public boolean getAutoFill() {
            return autoFillProperty().get();
        }

        public void setAutoFill(boolean value) {
            autoFillProperty().set(value);
        }

        public static MyCustomView createMyCustomView() {
            ObservableList<RowView> rowViews = FXCollections.observableArrayList();
            for (int i = 0; i < 20; i++) {
                RowView rv = new RowView();
                rv.setRow(i);
                rowViews.add(rv);
            }
            MyCustomView view = new MyCustomView();
            view.setRows(rowViews);
            return view;
        }
        }

Voici le fichier FXML de la vue principale, exemple.fxml:

<?import javafx.collections.FXCollections?>
<?import javafx.scene.layout.VBox?>
<?import sample.MyCustomView?>
<?import sample.RowView?>
<VBox fx:controller="sample.Controller"
      xmlns:fx="http://javafx.com/fxml"
      stylesheets="@custom.css">

    <!--GridLines and css don't work here-->
    <MyCustomView styleClass="grid" prefHeight="240.0" rotate="-90" alignment="CENTER"
                  fx:factory="createMyCustomView"/>
    <!--GridLines and css don't work here-->
    <MyCustomView styleClass="grid" prefHeight="240.0" rotate="-90" alignment="CENTER"
                  gridLinesVisible="true">
        <rows>
            <FXCollections fx:factory="observableArrayList">
                <RowView row="1" rowName="test"/>
                <RowView row="2" rowName="test"/>
                <RowView row="3" rowName="test"/>
                <RowView row="4" rowName="test"/>
                <RowView row="5" rowName="test"/>
            </FXCollections>
        </rows>
    </MyCustomView>

    <!--This works-->
    <MyCustomView prefHeight="240.0" rotate="-90" alignment="CENTER"/>
</VBox>

J'ai téléchargé tout le code de github https://github.com/spajo/ProblemExample

Author: Rafał Janicki, 2018-09-28