vocalionecho
vocalionecho

Reputation: 311

javafx 8, not using fxml, scene.lookup not finding node

In the following code, the primaryScene.lookup (line 30) returns null. But in debug mode (IntelliJ) I can drill in and see the node in the scene graph.

This is a self-contained example. No FXML.

The app just draws the Stage and Scene and then tries to select the Pane that is tagged with id="drawPane" using Scene.lookup.

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import static javafx.application.Application.launch;

public class Main extends Application {
    Scene primaryScene;
    Pane drawPane;

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

    }

    public void start(Stage primaryStage) {
        primaryScene = buildUI(primaryStage);
        if (primaryScene == null) throw new NullPointerException();

        drawPane = (Pane)primaryScene.lookup("#drawPane");
        if (drawPane == null) {
            throw new NullPointerException();
    }

    primaryStage.show();
}

private Scene buildUI(Stage primaryStage) {
    ScrollPane scrollPane;
    ImageView iv;

    BorderPane root = new BorderPane();
    Scene primaryScene = new Scene(root, 900, 800);
    initializePrimaryStage(primaryStage, primaryScene);
    initializeFrameContent(root);
    initializeContent(root);
    return primaryScene;

}

private void initializePrimaryStage(Stage primaryStage, Scene primaryScene) {
    primaryStage.setTitle("Image Clip Test");
    primaryStage.setScene(primaryScene);
    primaryStage.setWidth(400);
    primaryStage.setHeight(300);
    primaryStage.minWidthProperty().setValue(400);
    primaryStage.minHeightProperty().setValue(300);
}

private void initializeFrameContent(BorderPane root) {
    Button leftButton = new Button("LEFT");
    leftButton.setId("leftButton");
    Button rightButton = new Button("RIGHT");
    rightButton.setId("rightButton");
    Button topButton = new Button("TOP");
    rightButton.setId("topButton");

    StackPane leftPane = new StackPane(leftButton);
    leftPane.setAlignment(Pos.TOP_LEFT);

    StackPane rightPane = new StackPane(rightButton);
    rightPane.setAlignment(Pos.TOP_RIGHT);

    root.setLeft(leftPane);
    root.setTop(topButton);
    root.setRight(rightButton);
}

private void initializeContent(BorderPane root) {
    Pane drawPane = new Pane();
    drawPane.setId("drawPane");
    drawPane.setPrefSize(1000, 800);
    drawPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);

    ScrollPane scrollPane = new ScrollPane(drawPane);
    scrollPane.setPrefSize(300, 300);
    scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    scrollPane.setFitToHeight(true);
    scrollPane.setFitToWidth(true);
    scrollPane.setStyle("-fx-focus-color: transparent");

    root.setCenter(scrollPane);
    }
}

Upvotes: 2

Views: 1554

Answers (3)

Max Brito
Max Brito

Reputation: 21

Also stumbled on this situation. The solution above did not work, by inspecting the .fxml file that was generated by the Gluon WYSIWYG noticed that there were two id fields.

id="Content" fx:id="workpanel"

All that was needed was to remove the id="Content" and then the other id worked as expected.

Upvotes: 0

James_D
James_D

Reputation: 209225

Lookups do not work until CSS has been applied, which will usually not happen until the scene is laid out and rendered to the screen.

The following will force this to happen earlier, so you can access the lookup:

public void start(Stage primaryStage) {
    primaryScene = buildUI(primaryStage);
    if (primaryScene == null) throw new NullPointerException();

    primaryScene.getRoot().applyCss();

    drawPane = (Pane)primaryScene.lookup("#drawPane");
    if (drawPane == null) {
        throw new NullPointerException();
}

Upvotes: 7

stjepano
stjepano

Reputation: 1152

Strange but the call to new ScrollPane(drawPane) does not add the drawPane to the ScrollPane children list. I tried with scrollPane.setContent(drawPane), but it also does not work. This is why you can not look it up by the id. But you can lookup the drawPane by it's id after the window is displayed using following code.

Platform.runLater(() -> {
  drawPane = (Pane)primaryScene.lookup("#drawPane");
  if (drawPane == null) {
    throw new NullPointerException(); // this will not throw
  }
});

Upvotes: -1

Related Questions