JavaFX 8: changing the name of the main stage

How can you change the name of the main stage when the window is already displayed?

Stage#setTitle(String)

apparently not a gimmick.

+3


source to share


3 answers


setTitle(...)

seems to work fine:

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class UpdateStageTitle extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextField titleField = new TextField();
        titleField.textProperty().addListener((obs, oldText, newText) -> 
            primaryStage.setTitle(newText));
        HBox root = new HBox(5, new Label("Window title: "), titleField);
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 350, 75);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

      

Update the following comments.

For a more complex example, if you need to set this in a controller's initialization method, you need to arrange for the controller to refer to a stage before the method is called FXMLLoader

load()

. You can do this either by calling setController

on the bootloader or by calling setControllerFactory

. I usually prefer to set the controller to a factory as it allows the attribute fx:controller

to be used in the FXML (setting the controller directly disallows this).

So:

PrimaryStageAware.java:

package application;

import javafx.stage.Stage;

public interface PrimaryStageAware {
    public void setPrimaryStage(Stage primaryStage);
}

      



Main.java:

package application;

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


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("TitleSetter.fxml"));
            loader.setControllerFactory((Class<?> type) -> {
                try {
                    Object controller = type.newInstance();
                    if (controller instanceof PrimaryStageAware) {
                        ((PrimaryStageAware) controller).setPrimaryStage(primaryStage);
                    }
                    return controller ;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
            HBox root = loader.load();
            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

      

TitleSetter.fxml:

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

<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>

<HBox alignment="CENTER" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="application.TitleSettingController">
    <Label text="Update title: "/>
    <TextField  fx:id="titleField" />
</HBox>

      

TitleSettingController.java:

package application;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class TitleSettingController implements PrimaryStageAware {
    private Stage stage ;

    @FXML
    private TextField titleField ;

    @Override
    public void setPrimaryStage(Stage primaryStage) {
        this.stage = primaryStage ;
    }

    public void initialize()  {
        updateTitle("Initial title");
        titleField.textProperty().addListener((obs, oldTitle, newTitle) -> updateTitle(newTitle));
    }

    private void updateTitle(String title) {
        if (stage != null) {
            stage.setTitle(title);
        } else {
            System.out.println("Warning: null stage");
        }
    }

}

      

(With FXML in the same package along with Java files).

+6


source


I have worked with FXML. This would be my simple interface ChangeTitle.fxml

:

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

<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane fx:controller="ChangeTitleController" prefHeight="117.0" prefWidth="198.0" 
            xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65">
   <children>
      <TextField fx:id="input" layoutX="16.0" layoutY="32.0" onAction="#doStuff" />
   </children>
</AnchorPane>

      

Note A directive fx:controller=

that tells FXML which class to use as the controller. Also note that the TextField input

has an onAction directive in which the FXML runs doStuff()

as an actionHandler.

Now this is the class that launches the application ChangeTitle.class

:



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

public class ChangeTitle extends Application {

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

  @Override
  public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("ChangeTitle.fxml"));

    Scene scene = new Scene(root);
    primaryStage.setTitle("Change me");

    primaryStage.setScene(scene);
    primaryStage.show();
  }

}

      

Finally, we have a controller to do the actual work ChangeTitleController.class

. We use Stage primStage = (Stage) input.getScene().getWindow();

in the method doStuff()

to get the handle in the main step.

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

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class ChangeTitleController implements Initializable {

  @FXML private TextField input;

  @Override
  public void initialize(URL location, ResourceBundle resources) {

  }

  @FXML private void doStuff() {
    Stage primStage = (Stage) input.getScene().getWindow();
    primStage.setTitle(input.getText());

  }

}

      

+2


source


You can make the main class as a singleton and link to it via Main.getInstance ()

For example:

public class Main extends Application {

    private static Main instance;
    public static Main getInstance() {
        return instance;
    }

    private Stage primaryStage;

    @Override
    public void start(Stage primaryStage) throws Exception{
        instance = this;
        this.primaryStage = primaryStage;
        Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
        this.primaryStage.setTitle("Init title");
        this.primaryStage.setScene(new Scene(root, 900, 650));
        this.primaryStage.show();
        FlatterFX.style();
    }

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

    public void updateTitle(String title) {
        primaryStage.setTitle(title);
    }
}

      

+2


source







All Articles