Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen for WindowEvent.WINDOW_SHOWN in the nodes of the scene graph?

It seems WindowEvent.WINDOW_SHOWN never gets dispatched on any of the nodes in the scene graph, nor is there anyway (that I could find) to know when a node is visible/rendered/shown. For example:

TestLauncher.java

package com.example.javafx.event;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class TestLauncher extends Application
{
    public static void main(String[] args)
    {
        Application.launch(TestLauncher.class, args);
    }

    @Override
    public void start(Stage stage) throws Exception
    {
        Parent root = FXMLLoader.load(TestController.class.getResource("TestView.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
}

TestController.java

package com.example.javafx.event;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.TextField;
import javafx.stage.WindowEvent;

public class TestController implements Initializable
{
    @FXML private Parent root;
    @FXML private TextField serverAddressInput;
    @FXML private TextField usernameInput;

    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
        serverAddressInput.setText("127.0.0.1");

        //won't work because stage isn't visible yet
        trySetFocusOnUsernameInput1();

        //apparently Stage never passes on any WindowEvents to the children...
        trySetFocusOnUsernameInput2();
    }

    private void trySetFocusOnUsernameInput1()
    {
        usernameInput.requestFocus();
    }

    private void trySetFocusOnUsernameInput2()
    {
        root.addEventFilter(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>()
        {
            @Override
            public void handle(WindowEvent window)
            {
                usernameInput.requestFocus();
            }
        });

        root.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>()
        {
            @Override
            public void handle(WindowEvent window)
            {
                usernameInput.requestFocus();
            }
        });
    }

    public void handleWindowShownEvent()
    {
        usernameInput.requestFocus();
    }
}

TestView.fxml

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

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox
    xmlns:fx="http://javafx.com/fxml"

    fx:id="root"
    fx:controller="com.example.javafx.event.TestController"

    prefHeight="150"
    prefWidth="200"
>
    <children>
        <TextField fx:id="serverAddressInput" />
        <TextField fx:id="usernameInput" />
    </children>
</VBox>

So, actually, how else can a node become aware of the fact that it's visible/rendered/shown?

like image 516
Andrey Avatar asked Jan 20 '12 16:01

Andrey


People also ask

Can a node be placed in a scene JavaFX?

Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene in a Window that is showing. An application must attach nodes to such a Scene or modify them on the JavaFX Application Thread.

What is JavaFX scene node?

The JavaFX Node class, javafx. scene. Node , is the base class (superclass) for all components added to the JavaFX Scene Graph. The JavaFX Node class is abstract, so you will only add subclasses of the Node class to the scene graph.

What is scene graph and nodes in JavaFX?

In JavaFX, the GUI Applications were constructed using a Scene Graph. A scene graph is a data structure similar to tree, in modern graphical applications. It is the starting point of the application, and it is a collection of nodes.

What is the JavaFX scene graph?

A scene graph is a tree data structure, most commonly found in graphical applications and libraries such as vector editing tools, 3D libraries, and video games. The JavaFX scene graph is a retained mode API, meaning that it maintains an internal model of all graphical objects in your application.


1 Answers

I guess one of the possible solutions is to add the following method to TestController.java

    public void handleWindowShownEvent()
    {
        usernameInput.requestFocus();
    }

and then change the start method in TestLauncher to the following:

    @Override
    public void start(Stage stage) throws Exception
    {
        FXMLLoader loader = new FXMLLoader();
        Parent root = (Parent)loader.load(TestController.class.getResourceAsStream("TestView.fxml"));
        final TestController controller = (TestController)loader.getController();
        stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>()
        {
            @Override
            public void handle(WindowEvent window)
            {
                controller.handleWindowShownEvent();
            }
        });
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

I would really welcome other solutions as this one seems too clunky...

like image 146
Andrey Avatar answered Oct 08 '22 07:10

Andrey