1

I am creating a dialog and call Platform.runLater() in the controller initialize() method. When I try to open the dialog with showAndWait() it loads the FXML (I know it does because the warning is printed before Running Later and After first showAndWait) but doesn't open the dialog. Only a second call to showAndWait() will open it. It there a reason for this wired behavior or is this a bug?

The console output is:

Starting dialog creation
Running Later
After first showAndWait
Closing
After second showAndWait

but is should be:

Starting dialog creation
Init
Running Later
Closing
After first showAndWait
Closing
After second showAndWait

There is also this warning:

Apr 20, 2018 12:20:32 AM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 9.0.1 by JavaFX runtime of version 8.0.161

But as far as I know this just means that my JavaFX version is outdated.

Main class:

import java.io.IOException;
import java.util.List;
import java.util.Optional;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application{

    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(new BorderPane()));
        stage.show();
        System.out.println("Starting dialog creation");
        Dialog<Optional<List<String>>> popup = new Dialog<>();
        FXMLLoader loader = new FXMLLoader(Main.class.getClassLoader().getResource("Dialog.fxml"));
        try {
            popup.setDialogPane(loader.load());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Controller controller = loader.getController();
        controller.dialog = popup;
        popup.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
        popup.showAndWait();
        System.out.println("After first showAndWait");
        popup.showAndWait();
        System.out.println("After second showAndWait");
    }

}

Controller:

import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Dialog;

public class Controller {
    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    public Dialog<Optional<List<String>>> dialog;

    @FXML
    void initialize() {
        System.out.println("Init");
        Platform.runLater(() -> {
            System.out.println("Running Later");
            dialog.setResult(Optional.empty());
            dialog.setOnCloseRequest(e -> {
                System.out.println("Closing");
            });
        });
    }
}

FXML:

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

<?import javafx.scene.control.DialogPane?>


<DialogPane contentText="This is a text" headerText="Test" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller" />
Wendelin
  • 2,354
  • 1
  • 11
  • 28
  • 3
    Why are you calling `Platform.runLater()` in the `initialize()` method? – James_D Apr 19 '18 at 22:27
  • 1
    Could be because `runLater` puts the code you pass it at the end of it at the fx application thread, and `initialize` may also be executing on event thread. You can confirm this by printing `Platform.isFXApplicationThread()` in `initialize`. – Vince Apr 19 '18 at 22:32
  • 1
    @VinceEmigh `initialize()` is certainly executing on the FX Application Thread (it is invoked from `FXMLLoader.load()`, which is called from `start()`, which is called on the FX Application Thread). – James_D Apr 19 '18 at 22:33
  • @James_D I am calling `runLater` because I need to set some event listeners of the dialog. And I can't set them directly in the `initialize` method because at that point `dialog` (The field in the controller class) is still null. Just to confirm `Platform.isFXApplicationThread()` does return true. – Wendelin Apr 19 '18 at 22:47
  • 2
    Don't use `Platform.runLater`, instead just create the dialog in the initialize method of your controller rather than in the start method of your application. If you really want to create the dialog externally to the controller, then manipulate the dialog from within the controller (which I wouldn't recommend), then you can use the method in [Passing Parameters JavaFX FXML](https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) to pass the dialog instance to the controller after the initialize method has been invoked. – jewelsea Apr 19 '18 at 23:02
  • You have `xmlns="http://javafx.com/javafx/9.0.1"` in your FXML, but I'm guessing that you are running this on JavaFX 8, so that is probably why you are receiving the warning: "Loading FXML document with JavaFX API of version 9.0.1 by JavaFX runtime of version 8.0.161". – jewelsea Apr 19 '18 at 23:06
  • @jewelsea Thanks, this helped me, but does anyone still have an idea why the dialog doesn't open? – Wendelin Apr 20 '18 at 15:23

0 Answers0