TextField textProperty Listener через встроенные сцены JavaFX - PullRequest
0 голосов
/ 01 февраля 2020

Это может быть немного запутанным, но, пожалуйста, потерпите меня.

У меня есть 3 сцены, построенные с использованием SceneBuilder. Первый («Главный») я использую в качестве родительской сцены. Эта сцена содержит 1 AnchorPane, который содержит TabPane и ToolBar, который содержит 3 Buttons («Предыдущий», «Следующий» и «Закрыть»).

Вторая сцена («PersonaDetails» ") содержит AnchorPane, GridPane, число Textflow (которое я использую в качестве меток полей), несколько TextField и DatePicker. Вся эта сцена встроена в одну из вкладок TabPane в первой сцене («Основная»).

Третья сцена («Адрес») очень похожа на вторую, где она содержит AnchorPane, GridPane число Textflow (которое я использую в качестве меток полей), несколько TextField и ComboBox. Вся эта сцена встроена в другую вкладку TabPane в первой сцене («Основная»).

(я включил скрипт F XML для каждой ниже)

Позже приложение будет включать дополнительные сцены на дополнительной вкладке на панели вкладок на первой сцене («Основная»). Это приложение станет частью более крупного приложения и должно быть своего рода мастером, позволяющим регистрировать новых клиентов.

Кроме того, каждый файл F XML и его контроллер находятся в отдельных пакетах.

Эта проблема, с которой я столкнулся, заключается в том, что мне нужно добавить .textProperty() слушателей на несколько из Textfield, чтобы я мог включить или отключить «Next» Button на первой или родительской сцене (» Main ").

Я пробовал следующий код в классе 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);
            }
        });
    }
}

F XML Сценарии:

Основной

<?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>

PersonDetails

<?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>

Структура папок для проекта показана на рисунке ниже:

Folder Structure

1 Ответ

1 голос
/ 03 февраля 2020

Во-первых, я немного запутался с формулировкой «сцена» в вопросе. Я полагаю, что вы упомянули в вопросе об обработке узлов, потому что все fxmls обрабатываются в одной и той же сцене / сцене.

В любом случае, основная проблема заключается в методе инициализации MainController. Вы загружаете новый экземпляр PersonalDetailsController и работаете с ним, вместо того чтобы работать с контроллером, который фактически привязан к MainController.

При включении fxmls в f xml контроллер sub f xml уже будет введен в основной контроллер f xml. Поэтому я считаю, что изменение вашего MainController приведенный ниже код должен работать как положено.

Обновление: Извините за немного вводящую в заблуждение информацию. Правильно, вам нужно ввести контроллер с определенным соглашением об именах. Если вы включаете f xml, используя fx: include, чтобы получить контроллер, вам нужно ввести соглашение об именах <fxid>Controller и <fxid> для получения ссылки на узел.

Итак, учитывая ваш пример, для данного fx: включите строку:

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

ваш код в MainController должен быть:

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