首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >JavaFX创建包含应替换文本的节点的fxml模板

JavaFX创建包含应替换文本的节点的fxml模板
EN

Stack Overflow用户
提问于 2018-08-18 19:37:08
回答 1查看 414关注 0票数 0

我已经用场景构建器设计了一个布局。布局必须以相同的方式显示不同的信息。例如,我有一个用户名的标签,如果我用我的用户名登录,我希望显示它,这样就会有我的用户名。但我有很多这样的标签。有没有一种方法可以给标签一个文本(仅作为示例)%username%,并最终替换它。这样我就可以使用scenebuilder创建我的布局,然后总是按照我需要的方式放入内容中?我需要在运行时多次加载这些fxml文件,并且几乎总是使用新信息。

有什么想法吗?我知道我可以通过代码生成布局,然后很容易替换文本,但我喜欢场景构建器,只是想知道是否有一种简单的方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-19 00:23:15

您正在寻找的是Java、JavaFX和面向对象编程的非常基本的功能。

无需构建多个FXML文档或手动替换文本。您只需使用一个FXML文档并使用适当的MVC方法就可以做到这一点。

您将希望从所谓的数据模型或模型对象开始。在您的示例中,类似于User对象:

User.java

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class User {

    // These properties are used to display User data in the Scene
    private StringProperty username = new SimpleStringProperty();
    private StringProperty emailAddress = new SimpleStringProperty();

    /**
     * A simple constructor to build the User object with a username and email address
     */
    public User(String username, String emailAddress) {

        // Set the values for each of the User properties
        this.username.set(username);
        this.emailAddress.set(emailAddress);
    }

    public String getUsername() {
        return username.get();
    }

    public StringProperty usernameProperty() {
        return username;
    }

    public void setUsername(String username) {
        this.username.set(username);
    }

    public String getEmailAddress() {
        return emailAddress.get();
    }

    public StringProperty emailAddressProperty() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress.set(emailAddress);
    }
}

User.java中需要注意的重要一点是StringProperty声明。它们将在我们加载FXML控制器时发挥作用。

MainLayout.fxml

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>


<VBox xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <GridPane hgap="10.0" vgap="5.0">
        <columnConstraints>
          <ColumnConstraints hgrow="NEVER" minWidth="-Infinity" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="150.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Label text="Username:" />
            <Label text="Email Address:" GridPane.rowIndex="1" />
            <Label fx:id="lblUsername" GridPane.columnIndex="1" />
            <Label fx:id="lblEmailAddress" GridPane.columnIndex="1" GridPane.rowIndex="1" />
         </children>
      </GridPane>
   </children>
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
</VBox>

这只是一个简单的FXML布局,其中包含一个用于显示User信息的GridPane

MainController.java

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class MainController {

    // Here, we define our FXML elements. This allows us to access those elements directly from our Controller
    @FXML
    private Label lblUsername;
    @FXML
    private Label lblEmailAddress;

    // This is the User object that holds the data we want to display
    private User user;

    public MainController(User user) {
        this.user = user;
    }

    /**
     * The initialize() method is called when the FXML document is loaded. This is where we will populate our Scene
     * with the data from the User object passed to the controller's constructor. Since we already created our
     * constructor from the Main class, we have a valid User object to work with
     */
    @FXML
    private void initialize() {

        // There are two basic ways we can setup our Scene to display the User data. This demonstrates the proper Binding
        // method of doing so.

        // Bind the value of each Label to show the corresponding data from the User object
        lblUsername.textProperty().bind(user.usernameProperty());
        lblEmailAddress.textProperty().bind(user.emailAddressProperty());

        // The other method would be to simply set the text for each label. We will comment this out, however, as
        // using the above binding is preferred.
//        lblUsername.setText(user.getUsername());
//        lblEmailAddress.setText(user.getEmailAddress());

    }
}

还记得User对象是如何定义两个Property字段的吗?现在,在我们的MainController中可以看到,每个Label也有一个textProperty?当我们在该属性上调用bind()方法时,我们基本上是在告诉Java始终保持该textProperty等于user.usernameuser.emailAddress属性所包含的任何内容。

Main.java

现在,让我们创建将创建实际应用程序的类:

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

import java.io.IOException;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // First, let's create a sample User, passing the username and email address to the constructor
        User user = new User("zephyr", "zephyr@home.com");

        primaryStage.setTitle("Data Object Sample");

        try {
            // Tell JavaFX where to find the FXML file and create a loader for it
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MainLayout.fxml"));

            // Create a new MainController and pass our sample User to it
            MainController controller = new MainController(user);

            // Now that we've initialized our MainController with a User, let's set the controller for this FXML
            loader.setController(controller);

            // We may now load the FXML document and display the Scene
            primaryStage.setScene(new Scene(loader.load()));

            // Finally, show the Scene
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

就是这样!

正如您在运行应用程序时所看到的,MainController看到User并将usernameemailAddress属性绑定到在FXML中创建的Label节点。

您现在可以重用一个FXML布局来显示您想要的任何User

如果您想保持场景的加载并只更改setter,可以通过向MainController.java添加“User”来非常容易地实现

public void setUser (User user) {
    this.user = user;
}

每次调用该方法时,MainController中的User对象都会更改,JavaFX会注意到这一点,并且到每个Label的绑定都会自动更新,从而显示新用户的信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51908216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档