javajavafx我无法更改TextField的文本,除非我从这个方法中更改它,而且它实际上只发生在这个方法中,在我的控制器类中
我的程序非常简单,只有两个场景,第二个场景只是说“这是第二个场景”,在第一个场景中,你必须选择一个文件夹,然后它会出现在一个不可编辑的文本字段中。您可以使用“后退”和“下一步”按钮在这两个场景之间来回切换。问题是,当我转到第二个场景,然后再回到第一个场景时,文本字段是空的,当它真的应该显示我之前选择的文件夹的路径时,但当我重新选择它再次显示的文件夹时,但每次我更改场景时,它都会消失。TextField的FX:id是TextField。我试着让它再次将文本设置为文件夹的路径,但这次是用“后退”方法设置后退按钮。但是,如果出于某种原因,它不在OpenFolder方法中,那么它永远不会起作用,因为它在其他任何地方都不起作用。我想知道为什么它只适用于OpenFolder方法,而不适用于其他任何地方。这是我的控制器类:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import javafx.event.ActionEvent;
public class Controller {
private Stage stage;
private Scene scene;
private Parent root;
public Controller() {
}
@FXML
public void Next(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("scene2.fxml"));
stage = ((Stage)((Node)event.getSource()).getScene().getWindow());
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@FXML
public void Back(ActionEvent event) throws IOException{
Parent root = FXMLLoader.load(getClass().getResource("scene1.fxml"));
stage = ((Stage)((Node)event.getSource()).getScene().getWindow());
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@FXML
private TextField textfield = new TextField();
@FXML
private AnchorPane anchorid1;
@FXML
public static File thefolder;
@FXML
DirectoryChooser SongsOpener;
@FXML
public File OpenFolder(){
final DirectoryChooser SongsOpener = new DirectoryChooser();
stage = (Stage) anchorid1.getScene().getWindow();
thefolder = SongsOpener.showDialog(stage);
if (thefolder != null){
textfield.setText(thefolder.getAbsolutePath());
}
return thefolder;
}
}
这是我的FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="anchorid1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="411.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Text layoutX="326.0" layoutY="76.0" strokeType="OUTSIDE" strokeWidth="0.0" text="This is scene 1">
<font>
<Font size="33.0" />
</font>
</Text>
<Button layoutX="939.0" layoutY="373.0" mnemonicParsing="false" onAction="#Next" text="Next" />
<Label layoutX="63.0" layoutY="117.0" prefHeight="18.0" prefWidth="122.0" text="Songs folder :">
<font>
<Font size="20.0" />
</font></Label>
<Button layoutX="888.0" layoutY="121.0" mnemonicParsing="false" onAction="#OpenFolder">
<graphic>
<ImageView fitHeight="18.0" fitWidth="17.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../toppng.com-folder-icon-png-transparent-black-and-white-folder-ico-1589x1366.png" />
</image>
</ImageView>
</graphic>
</Button>
<TextField fx:id="textfield" layoutX="190.0" layoutY="119.0" prefHeight="23.0" prefWidth="685.0" />
</children>
</AnchorPane>
这里显示了我选择image文件夹后文本字段中的路径
但是,当我转到下一个场景并返回时,它消失了:image
# 1 楼答案
每次加载FXML文件时,
FXMLLoader
都会创建一组与FXML文件中的元素相对应的新控件。因此,如果重新加载第一个视图,就会得到一个新的TextField
,它显然不包含与前一个TextField
相同的文本,除非显式设置文本因此,您可以避免每次重新加载FXML文件(下面的第一个解决方案),或者创建一种机制,通过该机制,您可以在每次加载FXML时使用正确的值更新文本字段(下面的第二个解决方案,使用模型和绑定更新文本字段)
还请注意,每次更改视图时,绝对没有理由创建新的
Scene
。只需使用一个场景并替换它的root
解决方案加载每个视图一次
解决这个问题的一种方法是只加载每个FXML一次,然后在控制器中的两个视图之间切换:
App.java
View1Controller.java
View2Controller.java
View1.fxml
View2.fxml
使用模型存储状态的解决方案
另一种方法是创建包含所需数据的模型,并将文本字段中的文本绑定到模型中的适当属性。然后将相同的模型实例传递给每个控制器
例如:
ViewState.java
然后在
App.java
中:View1Controller.java
View2Controller
FXML文件的唯一更改是在第二个视图中向根元素添加
fx:id
:View2.fxml