JAVAFX:TextArea对象未输出文本



我在重新创建类似Winapi的类(MessageBox)时有一个问题。

下面提供的此Java类应该向用户传递简短的消息。

fxml文件是在场景构造中生成的。

坦率地说,我不知道为什么更新textarea字段不会使用提供的消息('string')更新窗口。

java(不工作

    import Util.WindowURLProvider; // this is a custom class which provides URL links to FXML pages
    import javafx.event.ActionEvent;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.TextArea;
    import javafx.stage.Stage;
    import java.io.IOException;
    public class StatusScreen {
        private static Stage statusStage = new Stage();
        private static WindowURLProvider windowURLProvider = new WindowURLProvider();
        public TextArea textArea;
        public Button okButton;
        public StatusScreen() {
        }
        public void setScreen(String title, String textToShow) throws IOException {
            textArea = new TextArea();
            textArea.appendText(textToShow); // the problem area
            statusStage.setTitle(title);
            statusStage.setScene(
                    new Scene(
                            FXMLLoader.load(windowURLProvider.getStatusWindowURL())
                    )
            );
            statusStage.show();
        }
        public void onOkButtonPressed(ActionEvent actionEvent) {
            statusStage.close();
        }
    }

fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<AnchorPane prefHeight="150." prefWidth="200.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="GUI.Screens.StatusScreen">
   <children>
      <GridPane prefHeight="150.0" prefWidth="200.0">
        <columnConstraints>
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints maxHeight="112.0" minHeight="10.0" prefHeight="112.0" vgrow="SOMETIMES" />
          <RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Button fx:id="okButton" mnemonicParsing="false" onAction="#onOkButtonPressed" prefHeight="25.0" prefWidth="213.0" text="OK" GridPane.rowIndex="1" />
            <TextArea fx:id="textArea" focusTraversable="false" prefHeight="200.0" prefWidth="200.0" promptText="SAMPLE_TEXT" text="" wrapText="true" />
         </children>
      </GridPane>
   </children>
</AnchorPane>

编辑:

java(工作

评论部分中有更好的解决方案:)

此示例使用场景的查找方法获取Textarea对象参考

import Util.WindowURLProvider;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import java.io.IOException;
public class StatusScreen {
    private static Stage statusStage = new Stage();
    private static WindowURLProvider windowURLProvider = new WindowURLProvider();
    public TextArea textArea;
    public Button okButton;
    public StatusScreen() {
    }
    public void setScreen(String title, String textToShow) throws IOException {
        Scene scene = new Scene(FXMLLoader.load(windowURLProvider.getStatusWindowURL()));
        textArea = (TextArea) scene.lookup("#textArea");
        textArea.appendText(textToShow);
        statusStage.setTitle(title);
        statusStage.setScene(scene);
        statusStage.show();
    }
    public void onOkButtonPressed(ActionEvent actionEvent) {
        statusStage.close();
    }
}

这是如何实现的示例:

public class StatusScreen {
    private static Stage statusStage = new Stage();
    private static WindowURLProvider windowURLProvider = new WindowURLProvider();
    @FXML
    public TextArea textArea;
    public StatusScreen() {
    }
    public void setScreen(String title, String textToShow) throws IOException {
        FXMLLoader loader = new FXMLLoader(windowURLProvider.getStatusWindowURL());
        loader.setController(this);
        Parent root = loader.load();
        textArea.appendText(textToShow);
        statusStage.setTitle(title);
        statusStage.setScene(new Scene(root));
        statusStage.show();
    }
    public void onOkButtonPressed(ActionEvent actionEvent) {
        statusStage.close();
    }
}

请注意,视图中的语句已删除了对控制器的明确引用

<AnchorPane prefHeight="150." prefWidth="200.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <GridPane prefHeight="150.0" prefWidth="200.0">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints maxHeight="112.0" minHeight="10.0" prefHeight="112.0" vgrow="SOMETIMES" />
                <RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
            </rowConstraints>
            <children>
                <Button fx:id="okButton" mnemonicParsing="false" onAction="#onOkButtonPressed" prefHeight="25.0" prefWidth="213.0" text="OK" GridPane.rowIndex="1" />
                <TextArea fx:id="textArea" focusTraversable="false" prefHeight="200.0" prefWidth="200.0" promptText="SAMPLE_TEXT" text="" wrapText="true" />
            </children>
        </GridPane>
    </children>
</AnchorPane>

您发布的代码创建两个文本字段:一个在FXML文件中,一个在Java中。您在Java中创建的文本字段上设置文本,但是显示的唯一文本字段是在FXML中创建的文本字段。因此,您永远不会看到您设置的文字。

"快速而肮脏"的修复程序只是直接从FXMLLoader检索文本字段。从FXML文件中删除fx:controller属性,然后进行

public class StatusScreen {
    private static WindowURLProvider windowURLProvider = new WindowURLProvider();
    public void setScreen(String title, String textToShow) throws IOException {
        FXMLLoader loader = new FXMLLoader(windowURLProvider.getStatusWindowURL());
        Stage statusStage = new Stage();
        statusStage.setTitle(title);
        statusStage.setScene(
                new Scene(loader.load())
        );
        TextArea textArea = (TextArea) loader.getNamespace().get("textArea");
        textArea.appendText(textToShow); 
        Button okButton = (Button) loader.getNamespace().get("okButton");
        okButton.setOnAction(this::onOkButtonPressed);
        statusStage.show();
    }
    public void onOkButtonPressed(ActionEvent actionEvent) {
        statusStage.close();
    }
}

一个更好的解决方案是使用单独的控制器类:

public class StatusScreenController {
    @FXML
    private TextArea textArea ;
    public void setText(String text) {
        textArea.setText(text);
    }
    public String getText() {
        return textArea.getText();
    }
    @FXML
    private void onOkButtonPressed() {
        textArea.getScene().getWindow().hide();
    }
}

将FXML中的fx:controller属性更改为指向此新控制器,然后只做:

public class StatusScreen {
    private static WindowURLProvider windowURLProvider = new WindowURLProvider();
    public void setScreen(String title, String textToShow) throws IOException {
        Stage statusStage = new Stage();
        FXMLLoader loader = new FXMLLoader(windowURLProvider.getStatusWindowURL());
        statusStage.setTitle(title);
        statusStage.setScene(
                new Scene(loader.load())
        );
        StatusScreenController controller = loader.getController();
        controller.setText(textToShow);
        statusStage.show();
    }
}

最后,您可以使用"自定义组件"方法,该方法已在另一个答案中概述。

最新更新