gpt4 book ai didi

java - 卡在 javafx 程序上,该程序不会将可注入(inject)字段加载到 FXML 文档中

转载 作者:行者123 更新时间:2023-12-01 19:33:29 31 4
gpt4 key购买 nike

我遇到的唯一问题是 getAll() 方法,它似乎在 PersonnelController 类中的位置立即运行。我也曾在其他很多地方尝试过,但都没有成功。 setAll() 方法看起来不错,我已经测试过 setAll() 向其传递值的方法可以将正确的值返回到 main 方法。他们只是出于某种原因没有在我需要的正确时间将值返回到 Controller 。

应该发生的是,用户输入用户名和密码,然后单击登录按钮,这就是在加载第二个场景之前将可注入(inject)值传递到 FXML 的位置。根据他们输入的用户名,第二个场景中将出现一组不同的图片和标签。我有程序调用的 getter 和 setter 方法来设置文本和图像。

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

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

这里 Starship.java 是具有 getter 和 setter 方法的两个类之一,登录屏幕的 Controller 中的 setAll() 方法和第二个屏幕的 Controller 中的 getAll() 方法调用这些方法(Personnel.java)。 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期间,initialize方法由FXMLLoader调用。由于您“预加载”了场景,因此当时尚未设置任何属性。

我强烈建议不要使用静态数据来传递信息。当然,能够访问数据很方便,但这是以无法控制何时/通过什么代码修改值以及永远无法同时拥有多于一艘船为代价的。

您可以使用 javafx 属性来处理这个问题。以下类设计只是缩写,缺少适当的可见性修饰符、setter、(属性)getter、初始化和构造函数,但我确信您可以自己添加:

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);

登录 Controller

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

人员 Controller

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 对象并查看人员场景中的变化。使 CrewMember 类不可变会稍微降低更新的复杂性,因为您不再需要使用绑定(bind),而只需要进行分配。此外,只有一个船舶+人员场景才允许您删除解除绑定(bind)逻辑,进一步简化逻辑...

关于java - 卡在 javafx 程序上,该程序不会将可注入(inject)字段加载到 FXML 文档中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58653142/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com