簡體   English   中英

卡在 javafx 程序上,該程序不會將可注入字段加載到 FXML 文檔中

[英]Stuck on a javafx program that won't load the injectable fields into FXML document

我遇到的唯一問題是 getAll() 方法,它似乎在我在 PersonnelController class 中的位置立即運行。 不過我在其他很多地方也試過了,但無濟於事。 setAll() 方法似乎很好,我已經測試過 setAll() 將值傳遞給的方法可以將正確的值返回給 main 方法。 他們只是出於某種原因沒有在我需要的正確時間將值返回給 controller。

應該發生的是用戶輸入他們的用戶名和密碼,然后單擊登錄按鈕,這就是在 secondScene 加載之前可以將可注入值傳遞給 FXML 的地方。 根據他們輸入的用戶名,一組不同的圖片和標簽將出現在第二個場景中。 我有程序調用的getter和setter方法來設置文本和圖像。

人員控制器.java

package application.controller;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

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

import application.Main;
import application.model.CrewMember;
import application.model.Starship;
import application.model.User;

public class PersonnelController implements Initializable {

    @FXML Label welcomeMsg;

    @FXML Label shipName;

    @FXML
    ImageView commandOfficer;

    @FXML
    ImageView engineOfficer;

    @FXML
    ImageView commOfficer;

    @FXML
    ImageView firstOfficer;

    @FXML
    ImageView nurse;

    @FXML
    ImageView medOfficer;

    @FXML
    ImageView navigator;

    @FXML
    ImageView helmsman;

    @FXML
    Label crew8;

    @FXML
    Label crew7;

    @FXML
    Label crew6;

    @FXML
    Label crew5;

    @FXML
    Label crew4;

    @FXML
    Label crew3;

    @FXML
    Label crew2;

    @FXML
    Label crew1;


    private Scene firstScene;

    public void getAll() {
          welcomeMsg.setText("Welcome, " + Starship.getCapt());
          shipName.setText(Starship.getShip());

          commandOfficer.setImage(CrewMember.getInput1());
          firstOfficer.setImage(CrewMember.getInput2());
          commOfficer.setImage(CrewMember.getInput3());
          engineOfficer.setImage(CrewMember.getInput4());
          helmsman.setImage(CrewMember.getInput5());
          navigator.setImage(CrewMember.getInput6());
          medOfficer.setImage(CrewMember.getInput7());
          nurse.setImage(CrewMember.getInput8());

          crew1.setText(CrewMember.getCrew1());
          crew2.setText(CrewMember.getCrew2());
          crew3.setText(CrewMember.getCrew3());
          crew4.setText(CrewMember.getCrew4());
          crew5.setText(CrewMember.getCrew5());
          crew6.setText(CrewMember.getCrew6());
          crew7.setText(CrewMember.getCrew7());
          crew8.setText(CrewMember.getCrew8());
}

    public void setFirstScene(Scene scene) {
        firstScene = scene;
    }


    public void openFirstScene(ActionEvent actionEvent) {    
        Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(firstScene);
    }

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

登錄控制器.java

package application.controller;

import java.io.FileNotFoundException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Scanner;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;
import javafx.geometry.*;

import application.Main;
import application.model.CrewMember;
import application.model.Starship;
import application.model.User;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;

import java.awt.Label;
import java.io.*;

public class LoginController implements Initializable {

    @FXML 
    private Button loginButton;

    @FXML
    private TextField username;

    @FXML
    private PasswordField password;

    private static Scene secondScene;   

    private void setAll(String user) {

        Starship.setShip(user);
        Starship.setCapt(user);

        CrewMember.setInput1(user);
        CrewMember.setInput2(user);
        CrewMember.setInput3(user);
        CrewMember.setInput4(user);
        CrewMember.setInput5(user);
        CrewMember.setInput6(user);
        CrewMember.setInput7(user);
        CrewMember.setInput8(user);

        CrewMember.setCrew1(user);
        CrewMember.setCrew2(user);
        CrewMember.setCrew3(user);
        CrewMember.setCrew4(user);
        CrewMember.setCrew5(user);
        CrewMember.setCrew6(user);
        CrewMember.setCrew7(user);
        CrewMember.setCrew8(user);


}

    public void setSecondScene(Scene scene) {
        secondScene = scene;
    }

    public void openSecondScene(ActionEvent actionEvent) {

        String user = username.getText();
        String pass = password.getText();
        setAll(user);   



         /* If the username/password are valid, open the Personnel viewer. 
        Otherwise, alert the user that credentials are invalid. */
        if(User.validate(user,pass,"data/users.csv")== true) {  

            Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();  
            primaryStage.setScene(secondScene);


          }
        else{

            User.invalid();

                }   
    }


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        assert loginButton != null : "fx:id=\"loginButton\" was not injected: check your FXML file '/Login.fxml'.";

            }
}

主.java

package application;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import application.model.CrewMember;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {

        try {
            /* getting loader and a pane for the first scene.
            Loader will then give a possibility to get related controller */
            FXMLLoader firstPaneLoader = new FXMLLoader(getClass().getResource("/Login.fxml"));
            Parent firstPane = firstPaneLoader.load();
            Scene firstScene = new Scene(firstPane);

            // getting loader and a pane for the second scene
            FXMLLoader secondPageLoader = new FXMLLoader(getClass().getResource("/Personnel.fxml"));
            Parent secondPane = secondPageLoader.load();
            Scene secondScene = new Scene(secondPane);

            // injecting second scene into the controller of the first scene
            application.controller.LoginController firstPaneController = (application.controller.LoginController) firstPaneLoader.getController();
            firstPaneController.setSecondScene(secondScene);

            // injecting first scene into the controller of the second scene
            application.controller.PersonnelController secondPaneController = (application.controller.PersonnelController) secondPageLoader.getController();
            secondPaneController.setFirstScene(firstScene);

            // open the login screen on start       
            primaryStage.setScene(firstScene);
            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }

            }

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

And here Starship.java is one of two classes with getter and setter methods that are called on by the setAll() method in the controller for the login screen and getAll() method in the controller for the second screen (Personnel.FXML).

人員.fxml

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>

<AnchorPane prefHeight="480.0" prefWidth="720.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.PersonnelController">
   <children>
      <ImageView fitHeight="90.0" fitWidth="120.0" onMouseClicked="#getAll" pickOnBounds="true" preserveRatio="true">
         <image>
            <Image url="@../Starfleet_Command_logo.jpg" />
         </image>
      </ImageView>
      <Label fx:id="welcomeMsg" layoutX="302.0" layoutY="45.0" prefHeight="16.0" prefWidth="116.0" AnchorPane.bottomAnchor="419.0" AnchorPane.leftAnchor="302.0" AnchorPane.rightAnchor="302.0" AnchorPane.topAnchor="45.0" />
      <Label fx:id="shipName" layoutX="302.0" layoutY="74.0" prefHeight="14.0" prefWidth="91.0" AnchorPane.bottomAnchor="390.0" AnchorPane.leftAnchor="302.0" AnchorPane.rightAnchor="302.0" AnchorPane.topAnchor="74.0">
         <font>
            <Font size="10.0" />
         </font>
      </Label>
      <GridPane layoutX="8.0" layoutY="131.0" prefHeight="347.0" prefWidth="703.0">
        <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <ImageView fx:id="commandOfficer" fitHeight="120.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true" GridPane.halignment="CENTER" GridPane.valignment="TOP" />
            <ImageView fx:id="engineOfficer" fitHeight="120.0" fitWidth="100.0" layoutX="48.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.valignment="TOP" />
            <ImageView fx:id="commOfficer" fitHeight="120.0" fitWidth="100.0" layoutX="10.0" layoutY="37.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="TOP" />
            <ImageView fx:id="firstOfficer" fitHeight="120.0" fitWidth="100.0" layoutX="10.0" layoutY="37.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="TOP" />
            <ImageView fx:id="nurse" fitHeight="120.0" fitWidth="100.0" layoutX="48.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP" />
            <ImageView fx:id="medOfficer" fitHeight="120.0" fitWidth="100.0" layoutX="10.0" layoutY="37.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP" />
            <ImageView fx:id="navigator" fitHeight="120.0" fitWidth="100.0" layoutX="10.0" layoutY="37.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP" />
            <ImageView fx:id="helmsman" fitHeight="120.0" fitWidth="100.0" layoutX="10.0" layoutY="37.0" pickOnBounds="true" preserveRatio="true" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP" />
            <Label text="Commanding Officer" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="80.0" layoutY="138.0" text="Chief Medical Officer" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="10.0" layoutY="89.0" text="Navigator" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="10.0" layoutY="89.0" text="Helmsman" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="10.0" layoutY="89.0" text="Chief Engineering Officer" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <padding>
                  <Insets bottom="30.0" />
               </padding>
            </Label>
            <Label layoutX="10.0" layoutY="89.0" text="Communications Officer" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="10.0" layoutY="89.0" text="First Officer" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label layoutX="80.0" layoutY="138.0" text="Nurse" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="30.0" />
               </GridPane.margin>
            </Label>
            <Label fx:id="crew1" text="Label" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew8" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew7" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew6" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew5" layoutX="10.0" layoutY="89.0" text="Label" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew4" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew3" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
            <Label fx:id="crew2" layoutX="10.0" layoutY="89.0" text="Label" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
               <GridPane.margin>
                  <Insets bottom="10.0" />
               </GridPane.margin></Label>
         </children>
      </GridPane>
      <Button layoutX="627.0" layoutY="32.0" mnemonicParsing="false" onAction="#openFirstScene" text="Log Out" />
   </children>
</AnchorPane>

登錄后,沒有設置任何應該由 getter 方法返回的標簽或圖像。 我只得到手動輸入的“歡迎”字符串。 所以,標題寫着“歡迎,null”。

在調用load期間, FXMLLoader會調用initialize方法。 那時還沒有設置任何屬性,因為您“預加載”了場景。

我強烈建議不要使用static數據來傳遞信息。 當然,能夠訪問數據很方便,但這是以無法控制何時/通過什么代碼修改值並且永遠無法同時擁有超過一艘船為代價的。

您可以改為使用 javafx 屬性來處理此問題。 以下 class 設計只是省略了適當的可見性修飾符、設置器、(屬性)獲取器、初始化和構造函數,但我相信您可以自己添加:

class Starship

   StringProperty name;
   ObjectProperty<CrewMember> captain;

   // possibly replace the following property with individual properties for roles
   // or use a ObservableMap<Role, CrewMember> instead???
   ObservableList<CrewMember> crew;
}

// could we make this immutable instead??? 
class CrewMember {
    StringProperty name;
    ObjectProperty<Image> image;
}

這允許您收聽船舶數據的修改:

Starship ship = new Starship();

firstPaneController.setShip(ship);
secondPaneController.setShip(ship);

登錄控制器

private Starship ship;

public void setShip(Starship ship) {
    this.ship = ship;
}

private void setAll(String user) {
    ship.setCaptain(new CrewMember(user));

    ship.getCrew().setAll(Stream.generate(() -> new CrewMember(user))
                                .limit(8)
                                .toArray(CrewMember[]::new));
}

人事控制器

private Label[] crewNameLabels;
private ImageView[] crewImageViews;

@Override
public void initialize(URL location, ResourceBundle resources) {
    crewNameLabels = new Label[] { crew1, crew2, crew3, crew4, crew5, crew6, crew7, crew8  };
    crewImageViews = new ImageView[] {
        commandOfficer,
        firstOfficer,
        commOfficer,
        engineOfficer,
        helmsman,
        navigator,
        medOfficer,
        nurse
    };
}

private final InvalidationListener crewUpdater = o -> {
    int newCrewSize = 0;
    if (ship != null) {
        List<Crew> crew = ship.getCrew();
        newCrewSize = ship.getCrew().size();
        if (newCrewSize > crewNameLabels.length) {
            newCrewSize = crewNameLabels.length;
        }
        for (int i = 0; i < newCrewSize; i++) {
            CrewMember c = crew.get(i);
            crewNameLabels[i].textProperty().bind(c.nameProperty());
            crewImageViews[i].imageProperty().bind(c.imageProperty());
        }
    }

    // unbind everything that has no corresponding CrewMember
    for (int i = newCrewSize; i < crewNameLabels.length; i++) {
        crewNameLabels[i].textProperty().unbind();
        crewNameLabels[i].setText("");
        crewImageViews[i].imageProperty().unbind();
        crewImageViews[i].setImage(null);
    }
};

private final InvalidationListener captainUpdater = o -> {
    CrewMember captain = null;
    if (ship != null) {
        captain = ship.getCaptain();
    }
    if (captain == null) {
        welcomeMsg.textProperty().unbind();
        welcomeMsg.setText("");
    } else {
        welcomeMessage.bind(Bindings.concat("Welcome, ", captain.nameProperty()));
    }
};

private Starship ship;

public void setShip(Starship ship) {
    if (this.ship != null) {
        // remove old listener when replacing the ship
        this.ship.getCrew().removeListener(crewUpdater);
        this.ship.captainProperty().removeListener(captainUpdater);
    }

    this.ship = ship;
    if (ship != null) {
        ship.getCrew().addListener(crewUpdater);
        ship.captainProperty().addListener(captainUpdater);
        shipName.textProperty().bind(ship.nameProperty());
    } else {
        shipName.textProperty().unbind();
        shipName.setText("");
    }

    // update content
    crewUpdater.invalidated(null);
    captainUpdater.invalidated(null);
}

這應該允許您在 JavaFX 應用程序線程的任何位置更新Starship object,並查看人員場景中的變化。 使CrewMember class 不可變會稍微降低更新的復雜性,因為您不再需要使用綁定,而只需要進行分配。 同樣,只有一個船+人員場景才能讓您刪除解除綁定的邏輯,從而進一步簡化邏輯......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM