我想在按上一个窗口中的按钮时出现的窗口中将侦听器添加到textField中。问题在于侦听器根本无法工作。它不会检测到任何变化。
public class WindowTwoController {
private Stage stage;
@FXML
private TextField imieTF = new TextField();
public void show() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("winTwo.fxml"));
Parent root = loader.load();
stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Sell Art");
stage.setScene(new Scene(root, 500, 500));
imieTF.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("textfield changed from " + oldValue + " to " + newValue);
});
stage.showAndWait();
}
我正在更改textField的值,但是没有任何内容输出到控制台。在上一个窗口中按下按钮时,将调用show方法。请帮我。这是我的winTwo.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<GridPane alignment="center" hgap="10" prefHeight="441.0" prefWidth="500.0" vgap="10" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="windowTwo.WindowTwoController">
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
<children>
<VBox prefHeight="354.0" prefWidth="455.0">
<children>
<Label alignment="CENTER" prefHeight="45.0" prefWidth="457.0" text="Sprzedaż dzieła">
<font>
<Font size="30.0" />
</font>
</Label>
<Separator prefWidth="200.0" />
<GridPane prefHeight="139.0" prefWidth="455.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label alignment="CENTER" prefHeight="40.0" prefWidth="220.0" text="Imię">
<font>
<Font size="28.0" />
</font>
</Label>
<Label alignment="CENTER" prefHeight="40.0" prefWidth="220.0" text="Nazwisko" GridPane.rowIndex="1">
<font>
<Font size="28.0" />
</font>
</Label>
<TextField fx:id="imieTF" GridPane.columnIndex="1">
<GridPane.margin>
<Insets right="20.0" />
</GridPane.margin></TextField>
<TextField fx:id="nazwiskoTF" GridPane.columnIndex="1" GridPane.rowIndex="1">
<GridPane.margin>
<Insets right="20.0" />
</GridPane.margin>
</TextField>
</children>
</GridPane>
<Separator prefWidth="200.0" />
<Label alignment="CENTER" prefHeight="17.0" prefWidth="450.0" text="Klient powracający">
<font>
<Font size="22.0" />
</font>
</Label>
<Separator prefWidth="200.0" />
<GridPane prefHeight="126.0" prefWidth="455.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label alignment="CENTER" prefHeight="40.0" prefWidth="220.0" text="Poziom Zaprzyjaźnienia" textFill="#00000080">
<font>
<Font size="19.0" />
</font>
</Label>
<ComboBox fx:id="cb" opacity="0.5" prefHeight="25.0" prefWidth="207.0" GridPane.columnIndex="1" />
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="175.0" text="Akceptuj" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="25.0" />
</GridPane.margin>
</Button>
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="175.0" text="Anuluj" GridPane.columnIndex="1" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="27.0" />
</GridPane.margin>
</Button>
</children>
</GridPane>
</children>
</VBox>
</children>
</GridPane>
答案 0 :(得分:3)
您应该像这样向私有成员imieTF添加注释
public class WindowTwoController {
@FXML
private TextField imieTF;
@FXML
private void initialize() {
imieTF.textProperty().addListener((observable, oldValue, newValue) ->
{
System.out.println("textfield changed from " + oldValue + " to " + newValue);
});
}
public static void show() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("winTwo.fxml"));
Parent root = loader.load();
stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Sell Art");
stage.setScene(new Scene(root, 500, 500));
stage.showAndWait();
}
}
这应将TextField实例绑定到控制器。但是据我发现,当创建属于fxml文件的窗口时,FXML将创建WindowTwoController的新实例。
有关其工作原理的基本示例,另请参见https://www.callicoder.com/javafx-fxml-form-gui-tutorial/。
请注意,对文本字段的所有操作都应该是JavaFX流的一部分,并且不能在WindowTwoController的手动实例中完成。请记住,JavaFX将在loader.load();
操作期间创建它自己的WindowTwoController实例。
答案 1 :(得分:0)
您的WindowTwoController#show()
方法是一个实例方法。这意味着您需要创建WindowTwoController
的实例才能调用show()
。但是,当您在FXML文件中使用fx:controller
时,FXMLLoader
将创建控制器类的它自己的实例。最终结果是,您添加侦听器的TextField
与FXMLLoader
创建,注入并添加到场景图的那个侦听器不同。
注意:您永远不会实例化将由FXMLLoader
注入的字段(即具有匹配的fx:id
属性的字段)。这样做充其量是在浪费资源,而在最坏的情况下会导致细微的错误。如果删除实例化逻辑导致NullPointerException
,则说明您的设置存在问题。
解决问题的一种方法是不使用fx:controller
而是手动设置控制器:
@FXML private TextField imieTF; // don't instantiate manually
public void show() {
FXMLLoader loader = new FXMLLoader(/* location */);
loader.setController(this); // must set before calling load()
Parent root = loader.load();
// remaining code omitted
}
另一种选择(在这种情况下,我个人更喜欢上面的选择)是遵循Gerben Jongerius's answer:将show()
设为静态方法,然后将add-listener-to-{{1} }逻辑插入TextField
方法中。如果您不知道,则在注入所有适当的字段后将调用initialize()
方法。
只是展示了另一种处理方式:
请注意,您不必在代码中添加initialize()
;您还可以在FXML文件中注册属性侦听器。这是 FXML简介的documented。
FXML:
ChangeListener
控制器方法:
<TextField onTextChange="#handleTextChange"/>