Объясните, почему объекты F XML были нулевыми - PullRequest
0 голосов
/ 13 апреля 2020

В моем коде я обнаружил проблему, заключающуюся в том, что все объекты, относящиеся к файлу F XML для класса контроллера, были нулевыми, хотя стиль из F XML работал и все теги fx: id мы одинаковы. Вот код F XML:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>

<VBox xmlns="http://javafx.com/javafx"
      xmlns:fx="http://javafx.com/fxml"
      alignment="center"
      spacing="10"
      prefHeight="750"
      prefWidth="1000"
      style="-fx-background-color: lightslategray">
    <padding><Insets top="0" bottom="10" left="10" right="10"></Insets></padding> <!-- Set the padding at 10px for each side of the window -->
    <Label fx:id="titleLabel" style="-fx-font-weight: bold; -fx-font-size: 32;" wrapText="true" text="Deck Title"/>
    <HBox spacing="10">
        <Button fx:id="backButton" text="Back" prefWidth="50"/>
        <ProgressBar fx:id="progressIndicator" GridPane.columnIndex="0" GridPane.rowIndex="0" prefWidth="920" progress="0.0"/>
    </HBox>
    <HBox spacing="20">
        <Label fx:id="qLabel" style="-fx-background-color: white; -fx-border-color: black" prefWidth="480" prefHeight="400" wrapText="true"/>
        <Label fx:id="aLabel" style="-fx-background-color: white; -fx-border-color: black; -fx-cursor: hand" prefWidth="480" prefHeight="400" wrapText="true" text="Click here to reveal the answer" onMouseClicked="#updateAnswer"/>
    </HBox>
    <HBox spacing="780">
        <Button fx:id="incorrectButton" text="Incorrect" prefWidth="100"/>
        <Button fx:id="correctButton" text="Correct" prefWidth="100"/>
    </HBox>
</VBox>

Вот код класса контроллера:

public class openCardsController {

@FXML Button backButton;
@FXML ProgressBar progressIndicator;
@FXML Label qLabel;
@FXML Label aLabel;
@FXML Label titleLabel;
@FXML Button incorrectButton;
@FXML Button correctButton;

public void openCards() throws IOException, ParseException {
    Stage window = Main.getStage();
    window.setWidth(1000);
    window.setHeight(750);

    // Had to swap Parent root = FXMLLoader.load(getClass().getResource("./mainPage.fxml")); for the following lines
    File file = new File(System.getProperty("user.dir") + "/src/flashcardApplication/openCardsPage.fxml");
    FXMLLoader loader = new FXMLLoader(file.toURI().toURL());
    loader.setController(this);


    VBox root = loader.load();
    backButton.setOnAction(e -> {
        try {
            backButtonPressed();
        } catch (IOException ignored) {}
    });
    incorrectButton.setOnAction(e -> incorrect());
    correctButton.setOnAction(e -> correct());
    window.setTitle("Flashcard Application - Open Cards");
    Scene mainMenuScene = new Scene(root, 1000, 750);
    window.setScene(mainMenuScene);
    int deckid = chooseCards();
    String fileURL = "ftp://appuser:pass123.@127.0.0.1/decks/" + Integer.toString(deckid) + ".json";
    URL url = new URL(fileURL); // Lines 43 to 45 come from https://www.javaworld.com/article/2073325/java-ftp-client-libraries-reviewed.html
    URLConnection urlc = url.openConnection();
    InputStream inputStream = urlc.getInputStream();
    JSONParser jsonParser = new JSONParser();
    JSONObject jsonObject = (JSONObject)jsonParser.parse(new InputStreamReader(inputStream, "UTF-8"));
    String title = (String) jsonObject.get("name");
    titleLabel.setText(title);
}

Мне пришлось удалить атрибут fx:controller="flashcardApplication.openCardsController из F XML file, и мне пришлось заменить строку Parent root = FXMLLoader.load(getClass().getResource("./mainPage.fxml")); на следующие строки:

File file = new File(System.getProperty("user.dir") + "/src/flashcardApplication/openCardsPage.fxml");
FXMLLoader loader = new FXMLLoader(file.toURI().toURL());
loader.setController(this);

Пожалуйста, кто-нибудь может объяснить, почему мне пришлось использовать другое решение, потому что я использовал решение одной строки в двух других F XML файлов и соответствующих им классов контроллеров без проблем

1 Ответ

0 голосов
/ 13 апреля 2020

Аннотированные @FXML поля инициализируются в контроллере при загрузке F XML. По умолчанию FXMLLoader создает экземпляр класса, заданного атрибутом fx:controller, и использует его в качестве контроллера.

Следовательно, в исходном коде контроллер не является текущим экземпляром OpenCardsController, на котором вызывается openCards(), но это новый экземпляр того же класса. Таким образом, @FXML -аннотированные поля инициализируются не в текущем экземпляре, а в новом экземпляре, который создается с помощью FXMLLoader.

, удаляя атрибут fx:controller и явно устанавливая контроллер в точный объект, который вам нужен (текущий экземпляр OpenCardsController), вы достигаете того, что вам нужно: контроллер теперь является текущим экземпляром, и FXML -аннотированные поля инициализируются в этом объекте.

Обратите внимание, что немного необычно загрузить файл F XML из самого контроллера. Типичный подход заключается в загрузке F XML из некоторого другого кода и отображении полученного пользовательского интерфейса; Контроллер обычно является отдельным объектом. Это может быть более естественным (и легче поддерживать в долгосрочной перспективе), если вы реорганизуете свой код так, чтобы F XML загружался откуда-то еще. (На самом деле это разделение проблем и проблема с одной ответственностью: контроллер должен отвечать только за обработку ввода пользователя из соответствующего файла F XML; он также не должен отвечать за загрузку F XML.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...