【问题标题】:JavaFX StackPane not showing object from inside of methodJavaFX StackPane 不显示方法内部的对象
【发布时间】:2018-11-10 01:09:34
【问题描述】:

好的,我用一个更简单的小例子重新编辑了这个问题。

我的问题是,我有一个 StackPane,myStackPane,我正在尝试将标签加载到上面。当程序第一次运行时,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>

FXMLSecond

<?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>

【问题讨论】:

标签: java javafx fxml


【解决方案1】:

主要问题是由

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 作为输入。

编辑 要让FXMLSecondControllerFXMLDocoment 添加标签,更改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());
    }
}

【讨论】:

  • 非常感谢您的回复。不过,您的示例并未将标签添加到 StackPane。这就是我的问题开始的地方。我现在明白创建一个新的FXML Loader 是在创建一个全新的 FXML,而不是将更改应用于当前打开的 FXML。那么,我可以获取对已经打开的StackPane 的引用并从FXMLsecondcontroller 添加标签吗?使用对StackPane 的静态引用是否合适?
  • “问题开始于”不是设置标签,而是获得正确的参考。我很高兴我的回答澄清了这一点。您可以获得静态引用,但最好通过 secondController.setChidren(myStackPane.getChildren()); 而不是 secondController.setTextProperty(label.textProperty()); 来路径堆栈窗格子项的引用。如果需要,我可以稍后将此选项添加到答案中。
  • 对不起,你是对的。我的问题是获得正确的参考。我仍然对“路径堆栈窗格子项的引用...”感到有些困惑,因此,如果您可以在有机会时添加/更新,那就太好了。当我看到您的代码时,也许它会更有意义。我只是迷失了如何在不创建新控制器的情况下引用现有的 StackPane。我正在查看This,但我也不确定这是否正确,而且我还没有机会使用我的代码进行尝试。
  • 更新了我的答案。希望对您有所帮助。
  • 我开始关注你在这里所做的事情......但是,我在这条secondController.setRefrences(myStackPane.getChildren(), label); 线上收到了NullPointerException。我假设这是因为 StackPane 是空的,并且没有孩子?编辑:但是,我添加了孩子,仍然得到 nullPointer。
猜你喜欢
  • 2020-04-11
  • 2023-03-28
  • 1970-01-01
  • 2014-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 2016-09-02
相关资源
最近更新 更多