java卡在javafx程序上,该程序无法将可注入字段加载到FXML文档中
我唯一的问题是getAll()方法,它似乎在PersonnelController类中的位置立即运行。不过,我在其他很多地方也试过,但都没有用。setAll()方法看起来不错,我已经测试过setAll()传递值的方法可以将正确的值返回给main方法。他们只是因为某些原因没有在我需要的正确时间将值返回给控制器
应该发生的是,用户输入用户名和密码,然后单击登录按钮,在加载第二个场景之前,可以将可注入值传递到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'.";
}
}
Main。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);
}
}
这里是星际飞船。java是两个具有getter和setter方法的类之一,这两个类分别由控制器中的setAll()方法在登录屏幕和控制器中的getAll()方法在第二个屏幕(personal.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方法应该返回的标签或图像都没有设置。我只得到手动输入的“欢迎”字符串。所以,标题是“欢迎,空。”
# 1 楼答案
在
load
的调用过程中,FXMLLoader
调用initialize
方法。因为您“预加载”了场景,所以当时没有设置任何属性我强烈建议不要使用
static
数据来传递信息。当然,能够访问数据是很方便的,但这样做的代价是无法控制何时/通过什么代码修改值,而且永远不能同时拥有多艘船舶您可以使用javafx属性来处理这个问题。下面的类设计只是省略了适当的可见性修饰符、setter、(属性)getter、initialisation和构造函数,但我相信您可以自己添加这些:
这允许您监听船舶数据的修改:
LoginController
人员控制器
这应该允许您在JavaFX应用程序线程的任何位置更新
Starship
对象,并查看人员场景中的更改。使CrewMember
类不可变将稍微降低更新的复杂性,因为您不再需要使用绑定,而只需要执行赋值。此外,只有单一的舰船+人员场景才能让你移除解除绑定的逻辑,从而进一步简化逻辑