java JavaFX 8:更改初级阶段的标题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26494865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:01:41  来源:igfitidea点击:

JavaFX 8: Changing title of primary stage

javajavafxjavafx-8

提问by Hannes

How can the title of the primary stage be changed, when the window is already showen?

当窗口已经显示时,如何更改初级阶段的标题?

Stage#setTitle(String)apparently does not the trick.

Stage#setTitle(String)显然不是诀窍。

回答by James_D

setTitle(...)seems to work fine here:

setTitle(...)似乎在这里工作正常:

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);
    }
}

Updatefollowing comments.

更新以下评论。

For a more complex example, if you need to set this in the controller's initialize method, you need to arrange for the controller to have a reference to the stage before the FXMLLoader's load()method is invoked. You can do this either by calling setControlleron the loader, or by calling setControllerFactory. I generally prefer setting the controller factory, as it allows for use of the fx:controllerattribute in FXML (setting the controller directly prohibits this).

对于更复杂的示例,如果需要在控制器的 initialize 方法中设置 this,则需要安排控制器在调用FXMLLoaderload()方法之前具有对舞台的引用。您可以通过调用setController加载程序或调用setControllerFactory. 我通常更喜欢设置控制器工厂,因为它允许使用fx:controllerFXML中的属性(直接设置控制器禁止这样做)。

So:

所以:

PrimaryStageAware.java:

PrimaryStageAware.java:

package application;

import javafx.stage.Stage;

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

Main.java:

主.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:

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:

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 the FXML in the same package alongside the Java files).

(将 FXML 与 Java 文件放在同一个包中)。

回答by Resturp

I worked this out using FXML. This would be my simple interface ChangeTitle.fxml:

我使用 FXML 解决了这个问题。这将是我的简单界面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>

Notice The fx:controller=directive that tells FXML which class to use as controller. Also notice That the TextField inputhas an onAction directive that tells FXML to run doStuff()as actionHandler.

注意fx:controller=告诉 FXML 使用哪个类作为控制器的指令。还要注意 TextFieldinput有一个 onAction 指令,它告诉 FXMLdoStuff()作为 actionHandler运行。

Now this is the class that starts the application ChangeTitle.class:

现在这是启动应用程序的类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();
  }

}

And finally we have a controller to do the actual work ChangeTitleController.class. We use Stage primStage = (Stage) input.getScene().getWindow();within the doStuff()method to get a handle on the primary stage.

最后我们有一个控制器来做实际的工作ChangeTitleController.class。我们Stage primStage = (Stage) input.getScene().getWindow();doStuff()方法中使用来获取初级阶段的句柄。

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());

  }

}

回答by Алексей Вишняков

You can make Main class as singleton and to contact him via Main.getInstance()

您可以将 Main 类设为单例并通过 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);
    }
}