当前位置: 首页 > 知识库问答 >
问题:

跨嵌入式场景的TextField textProperty侦听器JavaFX

唐晗昱
2023-03-14

这可能有点复杂,但请忍受我。

我用SceneBuilder构建了3个场景。第一个(“主”)我用作为父场景。此场景包含1个< code>AnchorPane,其中包含一个< code>TabPane和一个< code>ToolBar,其中包含3个< code >按钮(“上一个”、“下一个”和“关闭”)。

第二个场景(“PersonaDetails”)包含一个AnchorPane,一个GridPane以及许多Textflow(我将其用作字段标签)几个TextFieldDatePicker。整个场景嵌入到第一个场景(“主”)的 TabPane 上的一个选项卡中。

第三个场景(“Address”)与第二个非常相似,其中包含一个< code>AnchorPane、一个< code>GridPane、多个< code>Textflow(我将它用作字段标签)、几个< code>TextField和< code>ComboBox。整个场景嵌入到第一个场景(“Main”)的< code>TabPane上的其他选项卡中。

(我为下面的每一个都包含了FXML脚本。)

该应用程序稍后将在第一个场景(“主”)的TabPane上的附加选项卡上包含附加场景。此应用程序将构成更大应用程序的一部分,旨在成为一种允许注册新客户端的向导。

此外,每个FXML文件及其控制器都在单独的包中。

我遇到的这个问题是我需要添加< code >。几个< code>Textfield上的textProperty()侦听器,以便我可以启用或禁用第一个或父场景(“Main”)上的“Next”< code >按钮。

我在MainController类中尝试了以下代码,但它不起作用,尽管它不会产生任何错误。

package com.yas.registrationwizard.main;

import com.yas.registrationwizard.personaldetails.PersonalDetailsController;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.AnchorPane;

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

public class MainController implements Initializable {

    @FXML AnchorPane apMain;
    @FXML ToolBar tbMain;
    @FXML TabPane tpMain;

    @FXML Button btnPrevious;
    @FXML Button btnNext;
    @FXML Button btnClose;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../personaldetails/PersonalDetails.fxml"));
        try {
            fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        PersonalDetailsController personalDetailsController = fxmlLoader.getController();
        personalDetailsController.tfFirstName.textProperty().addListener((obs, oldVal, newVal) -> {
            if(newVal.equals("")) {
                btnNext.setDisable(true);
            } else {
                btnNext.setDisable(false);
            }
        });
    }
}

FXML 脚本如下所示:

主要的

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

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="apMain" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.main.MainController">
    <children>
        <ToolBar fx:id="tbMain" layoutX="259.0" layoutY="339.0" prefHeight="40.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="355.0">
            <items>
                <Pane prefHeight="30.0" prefWidth="370.0" />
                <Button fx:id="btnPrevious" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Previous" />
                <Button fx:id="btnNext" layoutX="10.0" layoutY="13.0" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false"  prefHeight="25.0" prefWidth="65.0" text="Next" />
                <Button fx:id="btnClose" layoutX="66.0" layoutY="13.0" maxHeight="25.0" maxWidth="65.0" minHeight="25.0" minWidth="65.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="65.0" text="Close" />
            </items>
        </ToolBar>
        <TabPane fx:id="tpMain" layoutX="14.0" layoutY="14.0" prefHeight="335.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
            <tabs>
                <Tab fx:id="tabPersonalDetails" text="Personal Deatils">
               <content>
                  <fx:include fx:id="apPersonalDetails" source="../personaldetails/PersonalDetails.fxml" />
               </content></Tab>
                <Tab fx:id="tabAddress" text="Address">
               <content>
                  <fx:include fx:id="apAddress" source="../address/Address.fxml" />
               </content></Tab>
            </tabs>
        </TabPane>
    </children>
</AnchorPane>

地址

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

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="apAddress" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="325.0" prefWidth="590.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.address.AddressController">
   <children>
      <GridPane fx:id="gpAddress" layoutX="195.0" layoutY="103.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="103.0" minWidth="3.0" prefWidth="82.0" />
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="219.0" minWidth="10.0" prefWidth="155.0" />
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="422.0" minWidth="10.0" prefWidth="274.0" />
          <ColumnConstraints hgrow="SOMETIMES" maxWidth="93.0" minWidth="0.0" prefWidth="78.0" />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="295.0" text="House Name / Number:" GridPane.columnIndex="1" GridPane.rowIndex="2">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin></Label>
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="246.0" text="Address Line 1:" GridPane.columnIndex="1" GridPane.rowIndex="3">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin></Label>
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="239.0" text="Address Line 2:" GridPane.columnIndex="1" GridPane.rowIndex="4">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin></Label>
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Town / City:" GridPane.columnIndex="1" GridPane.rowIndex="5">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin></Label>
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="237.0" text="Region / County:" GridPane.columnIndex="1" GridPane.rowIndex="6">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin></Label>
            <TextField fx:id="tfHseNameNum" GridPane.columnIndex="2" GridPane.rowIndex="2" />
            <TextField fx:id="tfAddLine1" GridPane.columnIndex="2" GridPane.rowIndex="3" />
            <TextField fx:id="tfAddLine2" GridPane.columnIndex="2" GridPane.rowIndex="4" />
            <TextField fx:id="tfTownCity" GridPane.columnIndex="2" GridPane.rowIndex="5" />
            <TextField fx:id="tfRegionCounty" GridPane.columnIndex="2" GridPane.rowIndex="6" />
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Postcode:" GridPane.columnIndex="1" GridPane.rowIndex="7">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin>
            </Label>
            <TextField fx:id="tfPostcode" GridPane.columnIndex="2" GridPane.rowIndex="7" />
            <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" prefHeight="17.0" prefWidth="234.0" text="Country:" GridPane.columnIndex="1" GridPane.rowIndex="8">
               <GridPane.margin>
                  <Insets right="10.0" />
               </GridPane.margin>
            </Label>
            <ComboBox fx:id="cboCountry" prefHeight="25.0" prefWidth="294.0" GridPane.columnIndex="2" GridPane.rowIndex="8" />
         </children>
      </GridPane>
   </children>
</AnchorPane>

人物详情

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

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

<AnchorPane fx:id="apPersonalDetails" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="325.0" prefWidth="590.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yas.registrationwizard.personaldetails.PersonalDetailsController">
   <children>
      <GridPane fx:id="gpPersonalDetails" layoutX="195.0" layoutY="103.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="37.0" prefWidth="37.0" />
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="236.0" minWidth="10.0" prefWidth="236.0" />
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="422.0" minWidth="10.0" prefWidth="277.0" />
          <ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="38.0" prefWidth="41.0" />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <TextField fx:id="tfFirstName" GridPane.columnIndex="2" GridPane.rowIndex="2" />
            <TextField fx:id="tfMidNameInit" GridPane.columnIndex="2" GridPane.rowIndex="3" />
            <TextField fx:id="tfLastName" GridPane.columnIndex="2" GridPane.rowIndex="4" />
            <DatePicker fx:id="dpDoB" prefHeight="25.0" prefWidth="365.0" GridPane.columnIndex="2" GridPane.rowIndex="5" />
            <TextField fx:id="tfNatInsNum" GridPane.columnIndex="2" GridPane.rowIndex="6" />
            <TextFlow fx:id="tflFirstName" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="2">
               <GridPane.margin>
                  <Insets right="10.0" top="10.0" />
               </GridPane.margin></TextFlow>
            <TextFlow fx:id="tflLastName" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="4">
               <padding>
                  <Insets right="10.0" top="10.0" />
               </padding>
            </TextFlow>
            <TextFlow fx:id="tflDoB" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="5">
               <padding>
                  <Insets right="10.0" top="10.0" />
               </padding>
            </TextFlow>
            <TextFlow fx:id="tflNatInsNum" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="6">
               <padding>
                  <Insets right="10.0" top="10.0" />
               </padding>
            </TextFlow>
            <TextFlow fx:id="tflMidNameInit" prefHeight="16.0" prefWidth="162.0" style="-fx-text-alignment: right;" styleClass="txtFlow" GridPane.columnIndex="1" GridPane.rowIndex="3">
               <padding>
                  <Insets right="10.0" top="10.0" />
               </padding>
            </TextFlow>
         </children>
      </GridPane>
   </children>
</AnchorPane>

项目的文件夹结构如下图所示:

共有1个答案

龚睿
2023-03-14

首先,我对问题中的“场景”一词有点困惑。我相信你在问题中提到的是关于处理节点的,因为所有fxmls都是在同一个场景/阶段处理的。

无论如何,该问题的主要问题在于MainController初始化方法。您正在加载一个新实例并对其进行处理,而不是处理实际绑定到MainController的控制器。

<罢工> 当在fxml中包含fxml时,子fxml的控制器将已经被注入到主fxml控制器中。 因此,我认为按如下方式更改主控制器代码应该可以正常工作。

更新:很抱歉有点误导性的信息。正确的做法是,您需要向控制器注入特定的命名约定。如果您使用fx:include包含一个fxml,那么为了获得控制器,您需要注入一个命名约定

因此,考虑到您的示例,对于给定的fx:include行:

<fx:include fx:id="apPersonalDetails" source="../personaldetails/PersonalDetails.fxml" />

您在主控制器中的代码应该是:

// For controller reference
@FXML PersonalDetailsController apPersonalDetailsController;

// For Node reference
@FXML AnchorPane apPersonalDetails;

因此,更新后的代码将如下所示:

import com.yas.registrationwizard.personaldetails.PersonalDetailsController;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.AnchorPane;

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

public class MainController implements Initializable {

    @FXML AnchorPane apMain;
    @FXML ToolBar tbMain;
    @FXML TabPane tpMain;

    @FXML Button btnPrevious;
    @FXML Button btnNext;
    @FXML Button btnClose;

    @FXML PersonalDetailsController apPersonalDetailsController;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        apPersonalDetailsController.tfFirstName.textProperty().addListener((obs, oldVal, newVal) -> {
            if(newVal.equals("")) {
                btnNext.setDisable(true);
            } else {
                btnNext.setDisable(false);
            }
        });
    }
}

 类似资料:
  • 问题内容: 我有一个使用javafx Scene来渲染某些东西的应用程序,并且我想将该渲染结果放入我在Javafx中创建的某些GUI中。我该怎么做? 基本上,有一些容器可以放入场景,然后将其放入GUI。 抱歉,如果是新手问题,我是JavaFX的新手 问题答案: 该场景只有一个顶级父节点作为根。您可以获取它并放入另一个场景。

  • 问题内容: 我当时在上网,但找不到很好的信息。我试图在每次运行应用程序时检测按键。我正在使用JavaFX并将其与FXML一起运行。我尝试了很多事情,但没有任何效果。请帮我。 问题答案: 您应该签出Ensemble示例。这是关键的侦听器代码。

  • 问题内容: 对于大型项目,有人告诉我,当您拥有扩展JPanels的类时,最佳实践是使用嵌套类来实现侦听器。例如,我可以拥有扩展JPanel的FactoryScreen类,并具有实现所有必要侦听器的嵌套类FactoryScreenBrain。 对于以这种方式封装我的类的特定优点或缺点,我一直无法得到很好的解释,并且直到现在,我始终只有可以扩展JPanel和实现侦听器的类。有人可以为此提供一些指导吗?

  • 我正在使用Realex Payments的HPP API开发一个卡支付页面,其中包含一个iFrame,用于托管Realex页面。在Realex请求表单上,我将字段HPP_POST_维度和HPP_POST_响应设置为我的URL,如下所示: 付款页: www.example.com/account/payment.html 隐藏字段值用于在HPP页面大小更改和事务完成时,使用事件侦听器将数据从Real

  • 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过watch选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。例如: <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question">

  • 1. 前言 本节介绍侦听器 watch 的使用方法。包括什么是侦听器,侦听器的特点,以及如何对不同类型的数据进行监听。其中重点掌握对不同类型的数据如何使用侦听器,了解它之后,在才能在之后的日常开发中熟练运用。 2. 慕课解释 Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。 — 官方定义 侦听器 watch 是 Vue 提供的一种用来观察和响应 Vue 实例上的数据