当前位置: 首页 > 知识库问答 >
问题:

JavaFX:数据绑定(textfield)可以在生产模式中使用吗?

解晟睿
2023-03-14

我有4个文本文件是通过FXML创建的。两个用于字符串模型类型。一个表示整数。一个给BigDecimal。问题发生在所有这些字段上(有时是一个字段,有时是几个字段)。因为我的数字字段可以有空值,所以我使用例如PropertyObject而不是IntegerProperty(来自openjfx的人建议这样做)。

那么这个是JavaFx bug还是什么?附言。我用felix osgi、weld cdi和PAX-我不知道这是否重要...

我的代码如下:

public class Task {

    private String name;

    private Integer order;

    private BigDecimal weight;

    private String comment;

    private final PropertyChangeSupport propertyChangeSupport;

    public Task() {
        this.propertyChangeSupport = new PropertyChangeSupport(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        String pv = this.name ;
        this.name = name;
        propertyChangeSupport.firePropertyChange("name", pv, name);
    }

    public Integer getOrder() {
        return order;
    }

    public void setOrder(Integer order) {
        Integer pv = this.order;
        this.order = order;
        propertyChangeSupport.firePropertyChange("order", pv, this.order);
    }

    public BigDecimal getWeight() {
        return weight;
    }

    public void setWeight(BigDecimal weight) {
        BigDecimal pv = this.weight;
        this.weight = weight;
        propertyChangeSupport.firePropertyChange("weight", pv, weight);
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        String pv = this.comment;
        this.comment = comment;
        propertyChangeSupport.firePropertyChange("comment", pv, this.comment);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

}
public class TaskAdapter {

    private StringProperty nameProperty;

    private ObjectProperty<Integer> orderProperty;

    private ObjectProperty<BigDecimal> weightProperty;

    private StringProperty commentProperty;

      public TaskAdapter(Task task) {
        try {
            nameProperty=new JavaBeanStringPropertyBuilder().bean(task).name("name").build();
            orderProperty=new JavaBeanObjectPropertyBuilder<Integer>().bean(task).name("order").build();
            weightProperty=new JavaBeanObjectPropertyBuilder<BigDecimal>().bean(task).name("weight").build();
            commentProperty=new JavaBeanStringPropertyBuilder().bean(task).name("comment").build();
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
        }
    }

    public StringProperty getNameProperty() {
        return nameProperty;
    }

    public ObjectProperty<Integer> getOrderProperty() {
        return orderProperty;
    }

    public ObjectProperty<BigDecimal> getWeightProperty() {
        return weightProperty;
    }

    public StringProperty getCommentProperty() {
        return commentProperty;
    }

}
public class SimpleBigDecimalStringConverter extends StringConverter<BigDecimal>{

    @Override
    public String toString(BigDecimal i) {
        if (i == null) {
            return "" ;
        } else {
            return i.toString();
        }
    }

    @Override
    public BigDecimal fromString(String string) {
        if (string.trim().length() == 0) {
            return null ;
        } else {
            try {
                return new BigDecimal(string);
            } catch (NumberFormatException nfe) {
                return null ;
            } 
        }
    }
}
public class SimpleIntegerStringConverter extends StringConverter<Integer>{

    @Override
    public String toString(Integer i) {
        if (i == null) {
            return "" ;
        } else {
            return i.toString();
        }
    }

    @Override
    public Integer fromString(String string) {
        if (string.trim().length() == 0) {
            return null ;
        } else {
            try {
                return Integer.valueOf(string);
            } catch (NumberFormatException nfe) {
                return null ;
            } 
        }
    }
}

正在初始化代码

Task task=new Task();
TaskAdapter adapter=new TaskAdapter(task);
nameTextField.textProperty().bindBidirectional(adapter.getNameProperty());
orderTextField.textProperty().bindBidirectional(adapter.getOrderProperty(),new SimpleIntegerStringConverter());
weightTextField.textProperty().bindBidirectional(adapter.getWeightProperty(),new BigDecimalStringConverter());
commentTextField.textProperty().bindBidirectional(adapter.getCommentProperty());

共有1个答案

屠泰平
2023-03-14

正在发生什么

JavaFX绑定在幕后使用WeakChangeListeners来实现绑定。这意味着,如果范围内没有对绑定的其他引用,则可以对绑定本身进行垃圾回收。在您的代码中,适配器被定义为局部变量,因此在gc运行时,它会在任意时间被过早地垃圾回收。

演示

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.converter.BigDecimalStringConverter;

public class POJOBindingExample extends Application {

    private TextField nameTextField = new TextField();
    private TextField orderTextField = new TextField();
    private TextField weightTextField = new TextField();
    private TextField commentTextField = new TextField();

    @Override
    public void start(Stage primaryStage) {
        Task task = new Task();
        TaskAdapter adapter = new TaskAdapter(task);
        nameTextField.textProperty().bindBidirectional(adapter.getNameProperty());
        orderTextField.textProperty().bindBidirectional(adapter.getOrderProperty(),new SimpleIntegerStringConverter());
        weightTextField.textProperty().bindBidirectional(adapter.getWeightProperty(),new BigDecimalStringConverter());
        commentTextField.textProperty().bindBidirectional(adapter.getCommentProperty());

        GridPane grid = new GridPane();
        grid.addRow(0, new Label("Name:"), nameTextField);
        grid.addRow(1, new Label("Order:"), orderTextField);
        grid.addRow(2, new Label("Weight:"), weightTextField);
        grid.addRow(3, new Label("Comment:"), commentTextField);

        Button showButton = new Button("Show Task");
        showButton.setOnAction(e -> {
            System.out.println(task.getName());
            System.out.println(task.getOrder());
            System.out.println(task.getWeight());
            System.out.println(task.getComment());
            System.out.println();
        });

        Button gcButton = new Button("Run GC");
        gcButton.setOnAction(e -> System.gc());

        HBox buttons = new HBox(10, showButton, gcButton);

        BorderPane.setAlignment(grid, Pos.CENTER);
        BorderPane.setAlignment(buttons, Pos.CENTER);
        BorderPane.setMargin(grid, new Insets(10));
        BorderPane.setMargin(buttons, new Insets(10));

        BorderPane root = new BorderPane(grid, null, null, buttons, null);

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
public class POJOBindingExample extends Application {

    private TextField nameTextField = new TextField();
    private TextField orderTextField = new TextField();
    private TextField weightTextField = new TextField();
    private TextField commentTextField = new TextField();
    private TaskAdapter adapter;

    @Override
    public void start(Stage primaryStage) {
        Task task = new Task();
        adapter = new TaskAdapter(task);

        // ... etc
    }
}
 类似资料:
  • javafx属性是将数据模型连接到javafx gui的好方法,因为它们的绑定模型实现了强大的通知更新机制。 属性和绑定并不严格地与GUI相关,而是对JavaBeans的扩展。 因此,我们希望在应用程序模型类中使用它们,而不引入对包的依赖关系,并且通常来自. 换句话说:(update) 我可能需要将应用程序分成两个模块。 一个模块应该只包含操作数据的类(模型类,说MVC)。 第二个模块将包含所有图

  • 问题内容: 我一直在使用babel-node和带有babelify转换的browserify开发站点,以支持ES6语法。 我只是想知道,我是否可以在生产环境中运行它, 而不是 在节点中运行ES6还需要其他哪些选项? 这是我正在运行的用于构建和开始开发的命令 这是我的开发依赖 问题答案: 对于客户端代码 ,您正在做正确的事情。并将其运送给客户。 对于服务器端代码 ,我将使用babel- cli 进行

  • 问题内容: 我对 Angularjs数据绑定 功能有疑问。 如果我写: 而且我在 controller.js中 是这样的: 结果将是“你好布鲁诺!” …这太棒了!现在,我编辑了模板: 而且我还在关闭主体之前添加了此javascript函数: 所以我的问题是: 在AngularJS中是否可以在经典javascript函数中使用数据绑定? 更新: 这样就解决了错误…但是仍然没有出现名称…我仍在努力中…

  • 我试过这个说法: 是一个JavaFX和返回一个。 在调用时,有一个初始化的字符串,但TextField没有显示任何内容。 我怎样才能完成呢?

  • Android Studio:3.1.0、3.1.1 分级:4.4 生成工具:3.1.0 我正在使用数据绑定库。当我向project添加布局文件或向布局文件中添加任何视图时,Android Studio无法为布局生成绑定类,直到重新构建项目。 布局文件: 我查看了Android Studio的日志,当布局文件发生变化时,总会有错误消息。

  • 我有一个TextField,它有一个TextFormatter,它有一个过滤器,接受TextField的输入,并确保它是双格式的。然后使用DoubleStringConverter将过滤后的文本转换为双精度值。这在自定义FXML组件中。请参见下面的示例。 另一个使用此组件的FXML组件... bindBidirectional()试图将文本字段的转换值绑定到其他地方存在的SimpleDoubleP