我目前正在尝试创建列表以显示在板上(每个列表都有按钮和标题以及一个额外的 vbox 来存储其中的内容)。当我创建一个新列表以在我的板上显示它时,所有带@FXML 注释的字段都保留为空(但对象的子项存在)。具体的代码行是:
ListCtrl listObject = new ListCtrl();
我怀疑喷油器有问题,因为我不太确定如何使用它。这是我的代码。
List.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.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="180.0" style="-fx-border-color: black; -fx-border-width: 10;" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.scenes.ListCtrl">
<children>
<HBox alignment="TOP_RIGHT" prefHeight="19.0" prefWidth="140.0">
<children>
<Button fx:id="listEditButton" mnemonicParsing="false" text="Edit" />
<Button fx:id="listCloseButton" mnemonicParsing="false" text="X" />
</children>
</HBox>
<Label id="listTitle" fx:id="listTitle" alignment="CENTER" prefHeight="17.0" prefWidth="206.0" text="Default List Name" />
<VBox fx:id="cardBox" prefHeight="142.0" prefWidth="140.0" />
<Button id="listAddCard" fx:id="listAddCard" alignment="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="202.0" text="Add card" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
列表的控制者
package client.scenes;
import jakarta.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.fxml.Initializable;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class ListCtrl extends AnchorPane implements Initializable{
@FXML
private Label listTitle;
@FXML
private VBox cardBox;
@FXML
private Button listAddCard;
@FXML
private Button listCloseButton;
@FXML
private Button listEditButton;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@Inject
public ListCtrl(){
super();
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("List.fxml"));
Parent root = loader.load();
//Node n = loader.load();
//this.getChildren().add(n);
} catch (IOException ix){
}
}
/** Sets the text of the title of the list
* @param text
*/
public void setListTitleText(String text) {
listTitle.setText(text);
}
public void addCardToList(Node card){
cardBox.getChildren().add(card);
}
/**
* @return the title of the list
*/
public Label getListTitle() {
return listTitle;
}
/**
* @return the Edit button of the list
*/
public Button getListEditButton() {
return listEditButton;
}
/**
* @return the X button for the list
*/
public Button getListCloseButton() {
return listCloseButton;
}
/**
* @return the list button of the list
*/
public Button getListAddCardButton() {
return listAddCard;
}
}
我正在创建新列表的代码部分
public void refresh() {
mainBoard.getChildren().clear();
var lists = fakeServer.getBoardLists();
data = FXCollections.observableList(lists);
for (BoardList currentList : data) {
ListCtrl listObject = new ListCtrl(); ///Instantiating a new list to be shown
listObject.setListTitleText(currentList.title); //Setting the title of the list
ObservableList<Card> cardsInList =
FXCollections.observableList(fakeServer.getCards(currentList));
for (Card currentCard : cardsInList) {
CardCtrl cardObject = new CardCtrl(); ///Instantiating a new card to be shown
cardObject.setCardTitleText(currentCard.title); //Setting the title of the card
listObject.addCardToList(cardObject); //Adding the card to the list
}
listObject.getListAddCardButton().setOnAction(event -> mainCtrl.showAddCard(currentList));
mainBoard.getChildren().add(listObject);
}
}
我尝试查找有关如何将注入器用于通过代码创建的对象(因此主板上还没有的对象)的信息,但没有成功。提前谢谢你!
编辑:
我把我的刷新方法改成了这个:
public void refresh() {
mainBoard.getChildren().clear();
var lists = fakeServer.getBoardLists();
data = FXCollections.observableList(lists);
for (BoardList currentList : data) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("List.fxml"));
ListCtrl listObject = loader.getController(); ///Instantiating a new list to be shown
listObject.setListTitleText(currentList.title); //Setting the title of the list
ObservableList<Card> cardsInList =
FXCollections.observableList(fakeServer.getCards(currentList));
for (Card currentCard : cardsInList) {
CardCtrl cardObject = new CardCtrl(); ///Instantiating a new card to be shown
cardObject.setCardTitleText(currentCard.title); //Setting the title of the card
listObject.addCardToList(cardObject); //Adding the card to the list
}
listObject.getListAddCardButton().setOnAction(event -> mainCtrl.showAddCard(currentList));
//mainBoard.getChildren().add(listObject);
}
}
现在 listObject 为空。我是否错误地使用了装载机?
总结OP下方的评论作为答案:
虽然其他解决方案也是可能的(例如使用 动态根创建自定义组件),但我建议在这里使用标准 FXML 方法。通过这个,我的意思是使用 FXML 文件来定义 UI 并在 UI 逻辑(控制器,它不应该是 UI 组件)和 UI 视图(FXML)之间保持一定程度的分离。
@FXML
-注释字段仅在调用FXMLLoader
时在load()
创建的控制器对象中初始化;它们并没有在通过调用构造函数创建的控制器类的其他实例中以某种方式神奇地初始化。
你应该这样移动not让你的控制器类成为
AnchorPane
(或任何其他UI类)的子类并且不应该从构造函数加载FXML(因为控制器是通过加载FXML创建的,而不是相反).
public class ListCtrl {
@FXML
private Label listTitle;
@FXML
private VBox cardBox;
@FXML
private Button listAddCard;
@FXML
private Button listCloseButton;
@FXML
private Button listEditButton;
/** Sets the text of the title of the list
* @param text
*/
public void setListTitleText(String text) {
listTitle.setText(text);
}
public void addCardToList(Node card){
cardBox.getChildren().add(card);
}
/**
* @return the title of the list
*/
public Label getListTitle() {
return listTitle;
}
/**
* @return the Edit button of the list
*/
public Button getListEditButton() {
return listEditButton;
}
/**
* @return the X button for the list
*/
public Button getListCloseButton() {
return listCloseButton;
}
/**
* @return the list button of the list
*/
public Button getListAddCardButton() {
return listAddCard;
}
}
将加载 FXML 的责任转移到您需要在那里定义 UI 的位置,并通过调用 FXML 上的
getController()
来检索控制器:
public void refresh() {
mainBoard.getChildren().clear();
var lists = fakeServer.getBoardLists();
data = FXCollections.observableList(lists);
for (BoardList currentList : data) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("List.fxml"));
Parent card = loader.load();
ListCtrl listObject = loader.getController();
listObject.setListTitleText(currentList.title); //Setting the title of the list
ObservableList<Card> cardsInList =
FXCollections.observableList(fakeServer.getCards(currentList));
for (Card currentCard : cardsInList) {
CardCtrl cardObject = new CardCtrl(); ///Instantiating a new card to be shown
cardObject.setCardTitleText(currentCard.title); //Setting the title of the card
listObject.addCardToList(cardObject); //Adding the card to the list
}
listObject.getListAddCardButton().setOnAction(event -> mainCtrl.showAddCard(currentList));
mainBoard.getChildren().add(card);
}
}