gpt4 book ai didi

javafx - 绑定(bind)监听器在 JavaFX 8 中无法正常工作

转载 作者:行者123 更新时间:2023-12-04 12:50:39 24 4
gpt4 key购买 nike

目前我正在学习如何正确使用绑定(bind)和绑定(bind)事件。我已经阅读了一本书的一章,一般来说,我在使用绑定(bind)方面没有问题。

为了测试我的知识,我编写了一个小的 JavaFX8 应用程序。我有 2 个 TextField,但目前我专注于一个名为“firstName”的 TextField。我正在使用 BooleanBinding。每当 TextField 被填充时,BooleanBinding 就会设置为“true”。如果字段中没有输入,则 BooleanBinding 设置为“false”。我的目标是在 BooleanBinding 发生变化时更新名为“statusLabel”的标签。

这是绑定(bind)的样子:

BooleanBinding nameEntered = firstName.textProperty().isNotEmpty();

这是我的 ChangeListener:

nameEntered.addListener((o, oldValue, newValue) -> {
statusLabel.setText(newValue.toString());
});

在短时间内,Listener 正常工作。当 BooleanBinding 发生变化时,标签也会更新。但是在一些输入更改(删除输入、再次填充等...)之后,标签不再更新。有什么解决办法吗?

完整代码如下:

FXML Controller :

package gui;

/*
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.StringBinding;
import javafx.beans.binding.When;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

*/
public class LayoutController implements Initializable {

/**
* Initializes the controller class.
*/
@FXML
private TextField firstName;

@FXML
private TextField secondName;

@FXML
private CheckBox checkBox1;

@FXML
private CheckBox checkBox2;

@FXML
private CheckBox checkBox3;

@FXML
private Label statusLabel;

@Override
public void initialize(URL url, ResourceBundle rb) {
BooleanBinding nameEntered = firstName.textProperty().isNotEmpty();
nameEntered.addListener((o, oldValue, newValue) -> {
statusLabel.setText(newValue.toString());
});
}
}

主视图.java:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author xyz
*/
public class MainView extends Application{

@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Layout.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Benutzerauswahl");
primaryStage.show();
}

public static void main(String args[]){
launch(args);
}
}

FXML 布局:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>


<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="310.0" prefWidth="343.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.LayoutController">
<center>
<AnchorPane prefHeight="371.0" prefWidth="380.0" BorderPane.alignment="CENTER">
<children>
<GridPane layoutX="50.0" layoutY="103.0" prefHeight="234.0" prefWidth="281.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="49.0" AnchorPane.topAnchor="50.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="155.0" minWidth="10.0" prefWidth="110.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="197.0" minWidth="10.0" prefWidth="171.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="40.0" minHeight="10.0" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="40.0" minHeight="10.0" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="400.0" minHeight="10.0" prefHeight="88.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="17.0" prefWidth="56.0" text="Vorname:" GridPane.halignment="CENTER" />
<Label prefHeight="17.0" prefWidth="69.0" text="Nachname:" GridPane.halignment="CENTER" GridPane.rowIndex="1" />
<TextField fx:id="firstName" prefHeight="25.0" prefWidth="144.0" GridPane.columnIndex="1" />
<TextField fx:id="secondName" prefHeight="25.0" prefWidth="144.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<CheckBox fx:id="checkBox1" layoutX="14.0" layoutY="42.0" mnemonicParsing="false" text="Kurs 1" />
<CheckBox fx:id="checkBox2" layoutX="14.0" layoutY="69.0" mnemonicParsing="false" text="Kurs 2" />
<CheckBox fx:id="checkBox3" layoutX="14.0" layoutY="96.0" mnemonicParsing="false" text="Kurs 3" />
<Label fx:id="statusLabel" layoutX="43.0" layoutY="132.0" prefHeight="17.0" prefWidth="84.0" text="Status" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
</center>
</BorderPane>

最佳答案

这实际上是 JavaFX Beans Binding suddenly stops working 的副本:问题是绑定(bind)正在“过早地被垃圾收集”,因为没有保留对它的实时引用。强制将引用保留在 Controller 中似乎有点棘手。

首先请注意,如果您实际绑定(bind)了一个 UI 元素的属性(只要显示它就必然在范围内),那么 UI 元素会间接保留对绑定(bind)的引用。因此,在您的代码中,这将解决问题:

statusLabel.textProperty().bind(nameEntered.asString());

(而不是您当前拥有的监听器)。如果您实际上不能使用绑定(bind),那么您似乎首先需要让 Controller 保留对绑定(bind)的引用:

public class LayoutController implements Initializable {

// existing code...

private BooleanBinding nameEntered ;

public void initialize(URL url, ResourceBundle rb) {
nameEntered = firstName.textProperty().isNotEmpty();
nameEntered.addListener((o, oldValue, newValue) -> {
statusLabel.setText(newValue.toString());
});
}

}

然后您还需要强制对 Controller 本身的引用保留在范围内:

public class MainView extends Application{

private LayoutController controller ;

@Override
public void start(Stage primaryStage) throws Exception {
FMXLLoader loader = new FXMLLoader(getClass().getResource("Layout.fxml"));
Parent root = loader.load();
controller = loader.getController();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Benutzerauswahl");
primaryStage.show();
}

public static void main(String args[]){
launch(args);
}
}

可能有更明显的方法可以做到这一点,但我找不到有效的方法。

关于javafx - 绑定(bind)监听器在 JavaFX 8 中无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39349468/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com