好的,我用一个更简单的小例子重新编辑了这个问题。
我的问题是,我有一个StackPane myStackPane
试图将Label加载到其中。程序首次运行时,StackPane为空。当我单击handleButtonAction
按钮时,它将带我进入另一个阶段,因此我可以在标签上输入所需的文本。保存新文本后,它将新设置传递回主控制器并更新标签文本。然后将标签添加到StackPane。
但是...。它不在堆栈窗格中显示新标签。我知道我正在使用该方法,并且可以正确传递变量,因为我可以System.out.println
进行所有操作,而且都非常合适。但是为什么不将其添加到StackPane中呢?
感谢大家!
问题.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Problems extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXMLDocumentController
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FXMLDocumentController implements Initializable {
@FXML
private Button button;
@FXML
private StackPane myStackPane;
private Label label = new Label("Text 1");
@FXML
private void handleButtonAction(ActionEvent event) {
FXMLLoader secondLoader = new FXMLLoader();
secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));
try {
secondLoader.load();
} catch (IOException e) {
}
FXMLSecondController secondController = secondLoader.getController();
secondController.setFieldText(label.getText());
Parent p = secondLoader.getRoot();
Stage stage = new Stage();
stage.setScene(new Scene(p));
stage.showAndWait();
}
public void putLabelOnStackPane(String value) {
label.setText(value);
myStackPane.getChildren().add(label);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
FXMLSecondController
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class FXMLSecondController implements Initializable {
@FXML
private Button saveText;
@FXML
private TextField textField;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private void saveTextBtnPressed(ActionEvent event) {
FXMLLoader firstLoader = new FXMLLoader();
firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));
try {
firstLoader.load();
} catch (IOException e) {
}
FXMLDocumentController firstController = firstLoader.getController();
firstController.putLabelOnStackPane(textField.getText());
Stage stage = (Stage) saveText.getScene().getWindow();
stage.close();
}
public void setFieldText(String value) {
textField.setText(value);
}
}
FXML文件
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="problems.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="128.0" layoutY="14.0" onAction="#handleButtonAction" text="Click Me!" />
<StackPane fx:id="myStackPane" layoutX="61.0" layoutY="45.0" prefHeight="150.0" prefWidth="200.0" />
</children>
</AnchorPane>
FXML第二
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.1" fx:controller="problems.FXMLSecondController">
<children>
<Button fx:id="saveText" layoutX="274.0" layoutY="106.0" mnemonicParsing="false" onAction="#saveTextBtnPressed" text="Button" />
<TextField fx:id="textField" layoutX="226.0" layoutY="175.0" />
</children>
</AnchorPane>
最佳答案
主要问题是
FXMLLoader firstLoader = new FXMLLoader();
firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));
您实际上构造了一个新的
FXMLLoader
,而不是获得对打开的引用。例如,可以使用静态成员(请参见here)来获取对打开的
FXMLLoader
的引用,但是最好使用稍微不同的方法:FXMLDocumentController.java
public class FXMLDocumentController implements Initializable {
@FXML
private Button button;
@FXML
private StackPane myStackPane;
private Label label = new Label("Text 1");
@FXML
private void handleButtonAction(ActionEvent event) {
FXMLLoader secondLoader = new FXMLLoader();
secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));
try {
secondLoader.load();
} catch (IOException e) {e.printStackTrace(); }
FXMLSecondController secondController = secondLoader.getController();
//secondController.setFieldText(label.getText());
secondController.setTextProperty(label.textProperty());
Parent p = secondLoader.getRoot();
Stage stage = new Stage();
stage.setScene(new Scene(p));
stage.showAndWait();
myStackPane.getChildren().add(label);
}
/*
public void putLabelOnStackPane(String value) {
label.setText(value);
myStackPane.getChildren().add(label);
}*/
@Override
public void initialize(URL url, ResourceBundle rb) { //no need to implement Initializable
//if initialize not used
}
}
FXMLSecondController.java
public class FXMLSecondController implements Initializable {
@FXML
private Button saveText;
@FXML
private TextField textField;
private StringProperty labelStringProperty;
@Override
public void initialize(URL url, ResourceBundle rb) {
textField.setEditable(true);
}
@FXML
private void saveTextBtnPressed(ActionEvent event) {
/** By doing so you actually construct a new FXMLDocument
FXMLLoader firstLoader = new FXMLLoader();
firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));
try {
firstLoader.load();
} catch (IOException e) {
}
FXMLDocumentController firstController = firstLoader.getController();
firstController.putLabelOnStackPane(textField.getText());
*/
labelStringProperty.set(textField.getText());
Stage stage = (Stage) saveText.getScene().getWindow();
stage.close();
}
/*
public void setFieldText(String value) {
textField.setText(value);
}*/
public void setTextProperty(StringProperty labelStringProperty) {
this.labelStringProperty = labelStringProperty;
textField.setText(labelStringProperty.get());
}
}
还可以考虑使用Dialog作为输入。
编辑
要使
FXMLSecondController
为FXMLDocoment
添加标签,请更改FXMLDocumentController
以将所需的引用传递给FXMLSecondController
:public class FXMLDocumentController {
@FXML
private Button button;
@FXML
private StackPane myStackPane;
private Label label = new Label("Text 1");
@FXML
private void handleButtonAction(ActionEvent event) {
FXMLLoader secondLoader = new FXMLLoader();
secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));
try {
secondLoader.load();
} catch (IOException e) {e.printStackTrace(); }
FXMLSecondController secondController = secondLoader.getController();
secondController.setRefrences(myStackPane.getChildren(), label);
Parent p = secondLoader.getRoot();
Stage stage = new Stage();
stage.setScene(new Scene(p));
stage.showAndWait();
}
}
并让
FXMLSecondController
使用这些引用:public class FXMLSecondController {
@FXML
private Button saveText;
@FXML
private TextField textField;
private ObservableList<Node> children;
private Label label;
@FXML
private void saveTextBtnPressed(ActionEvent event) {
label.setText(textField.getText());
children.add(label);
Stage stage = (Stage) saveText.getScene().getWindow();
stage.close();
}
public void setRefrences(ObservableList<Node> children, Label label) {
this.children = children;
this.label = label;
textField.setText(label.getText());
}
}