我在重新创建类似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();
}
}
最后,您可以使用"自定义组件"方法,该方法已在另一个答案中概述。