Frizi
Frizi

Reputation: 53

issue with using extended JavaFX Class Dialog<R> and initializing the DialogPane

I use an extended Dialog class in my JavaFX application, but I failed to initialize the fields of the DialogPane. It seems the initialize method is never invoked. I make several modifications of the program code, unfortunately I do not have success. Therefore I hope you can help me. Thanks!

The application is reduced to a minimum: the main program starts via ControllerFactory the PortalController. There is a button to open my 'DialogFriZi'. The related DialogPane contains a label. The initializing of this label failed.

main program:

public class Main extends Application {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private final String FXML_PORTAL = "portal.fxml";
private MyHandler myHandler = new MyHandler();

@Override
public void init() {
    try{
        // Thread.currentThread is the FX-Launcher thread:
        Thread.currentThread().setUncaughtExceptionHandler(myHandler);
        try {
            logger.addHandler(new FileHandler("java.myLOG"));
        }
        catch (IOException e) {
            throw new IllegalStateException("IOException when adding File Handler");
        }
    }
    catch (Exception ex) {
        myHandler.uncaughtException(Thread.currentThread(), ex);
        throw(ex);
    }
}
@Override
public void start(Stage primaryStage) {
    try{
        logger.info("Test Application started");
        Thread.currentThread().setUncaughtExceptionHandler(myHandler);
        try{
            URL location = new URL(this.getClass().getResource("resources/fxml/" + FXML_PORTAL).toString());
            FXMLLoader loader = new FXMLLoader(location);
            loader.setControllerFactory(new SimpleControllerFactory(primaryStage));
            Pane root = loader.load();
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.setTitle("*** TEST App ***");
            primaryStage.show();
        }
        catch(IOException ex) {
            ex.printStackTrace();
            throw new IllegalStateException("check program source code!");
        }
    }
    catch(Exception ex) {
        myHandler.uncaughtException(Thread.currentThread(), ex);
        throw(ex);
    }
}

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

class MyHandler implements Thread.UncaughtExceptionHandler{
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        logger.log(Level.SEVERE, "** STOPP ** due to uncaught exception", throwable);
        Platform.exit();
    }
}

}

ControllerFactory

public class SimpleControllerFactory implements Callback<Class<?>,Object> {
private static final Logger logger = Logger.getLogger(SimpleControllerFactory.class.getName());
private final Stage primaryStage;
// types of controller
public SimpleControllerFactory(Stage stage) {
    this.primaryStage = stage;
}
public SimpleControllerFactory() { this(null); }

@Override
public Object call(Class<?> type) {
    try {
        for (var c : type.getConstructors()) {

            switch(c.getParameterCount()) {
                case 0 -> { }
                case 1 -> {
                    if ( c.getParameterTypes()[0] == Stage.class) {
                        return c.newInstance(primaryStage) ;
                    }
                    else;
                }
                default -> { }
            }
        }
        return type.getDeclaredConstructor().newInstance();
    }
    catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException ex) {
        logger.log(Level.SEVERE,ex.toString(),ex);
        throw new RuntimeException(ex);
    }
}

}

PortalController

public class PortalController implements Initializable {

private static final Logger logger = Logger.getLogger(PortalController.class.getName());
private final Stage recentStage;
private ResourceBundle resourceBundle;

public PortalController(Stage stage) {
    this.recentStage = stage;
}
public PortalController() {
    this(null);
}

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
    this.resourceBundle = resourceBundle;
}

@FXML
private void start(ActionEvent event) {
    DialogFriZi dialog = null;
    dialog = new DialogFriZi(recentStage);
    Optional<Boolean> result = dialog.showAndWait();
}

}

related FXML file

<VBox prefHeight="500.0" prefWidth="400.0" spacing="5.0" style="-fx-padding: 5 5 5 5;-fx-font-size: 11px" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="TestSimpleDialog.PortalController">
<children>
    <HBox alignment="CENTER">
        <children>
            <Button mnemonicParsing="false" onAction="#start" text="start FriZi dialog">
                <HBox.margin>
                    <Insets top="50.0" />
                </HBox.margin>
            </Button>
        </children>
    </HBox>
</children>

the extended Dialog class

public class DialogFriZi extends Dialog<Boolean> {

@FXML private ButtonType okButtonType;
@FXML Label label;

private static final Logger logger = Logger.getLogger(DialogFriZi.class.getName());
private final Stage recentStage;

public DialogFriZi(Stage primaryStage) {
    this.recentStage = primaryStage;
    runDialog();
}
public DialogFriZi() {
    this(null);
}

@FXML private void initialize() {
    System.out.println("start initializing");
    label.setText("hello");
}

private void runDialog() {
    FXMLLoader loader = new FXMLLoader();
    try {
        loader.setLocation(new URL
                (this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));
        DialogPane dialogPane = loader.load();
        loader.setController(this);
        initOwner(recentStage);

        initModality(Modality.APPLICATION_MODAL);
        setResizable(true);
        setTitle("FriZi Dialog");
        setDialogPane(dialogPane);

    }
    catch (IOException e) {
        String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
        logger.log(Level.SEVERE,message);
        throw new IllegalStateException(message);
    }
}

}

related FXML file

<DialogPane prefHeight="400.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
<content>
    <HBox prefHeight="100.0" prefWidth="200.0">
     <children>
        <Label fx:id="label" text="Label" />
     </children></HBox>

</content>
<buttonTypes>
    <ButtonType buttonData="OK_DONE" text="ok" />
    <ButtonType buttonData="CANCEL_CLOSE" text="Abbrechen" />
</buttonTypes>

Upvotes: 0

Views: 110

Answers (1)

James_D
James_D

Reputation: 209299

The initalize() method is invoked on the controller, if there is one, during the execution of the load() method. You are setting the controller after calling load(), so when load() runs, there is no controller. You need to change the order of the calls:

private void runDialog() {
    FXMLLoader loader = new FXMLLoader();
    try {
        loader.setLocation(new URL
                (this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));

        loader.setController(this);

        DialogPane dialogPane = loader.load();
        // loader.setController(this);
        initOwner(recentStage);

        initModality(Modality.APPLICATION_MODAL);
        setResizable(true);
        setTitle("FriZi Dialog");
        setDialogPane(dialogPane);

    }
    catch (IOException e) {
        String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
        logger.log(Level.SEVERE,message);
        throw new IllegalStateException(message);
    }
}

Upvotes: 2

Related Questions