将Label的文本属性(在FXML文件中)绑定到IntegerProperty(在控制器中) [英] Binding a Label's text property (in an FXML file) to an IntegerProperty (in a controller)

查看:1699
本文介绍了将Label的文本属性(在FXML文件中)绑定到IntegerProperty(在控制器中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在FXML文件中的Label和关联控制器中的IntegerProperty之间设置了一个数据绑定。问题是,当初始化时标签被设置为正确的值,当属性的值改变时,它不会更新。

I've set up a data binding between a Label in an FXML file and an IntegerProperty in the associated controller. The problem is that, while the label gets set to the correct value upon initialization, it is not updating when the property's value changes.

FXML文件

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

<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<GridPane xmlns:fx="http://javafx.com/fxml"
   fx:controller="application.PaneController" minWidth="200">
   <Label id="counterLabel" text="${controller.counter}" />
   <Button translateX="50" text="Subtract 1"
      onAction="#handleStartButtonAction" />
</GridPane>

控制器

package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;

public class PaneController implements Initializable
{
    private IntegerProperty counter;

    public int getCounter()
    {
        return counter.get();
    }

    public void setCounter(int value)
    {
        counter.set(value);
    }

    public PaneController()
    {
        counter = new SimpleIntegerProperty(15);
    }

    @Override
    public void initialize(URL url, ResourceBundle resources)
    {
    }

    @FXML
    private void handleStartButtonAction(ActionEvent event)
    {
        setCounter(getCounter() - 1);
        System.out.println(getCounter());
    }
}

期望

每次按下Subtract 1按钮,计数器将递减1,counterLabel将自动更新。

Each time I push the "Subtract 1" button, the counter will decrement by 1, and the counterLabel will update automatically.

现实

计数器递减1,但是counterLabel仍然保持在15(初始值)。

The counter does decrement by 1, but the counterLabel remains stuck at 15 (the initial value).

问题

我受到印象(例如,从这个论坛帖子),我做了什么应该工作。我缺少什么?

I was under the impression (e.g., from this forum post) that what I've done should work. What am I missing?

推荐答案

您需要添加一个JavaFX特定的访问器变量名称 属性

You need to add a JavaFX specific accessor variableNameProperty to the controller:

public IntegerProperty counterProperty() {
    return counter;
}

编辑:更多细节

API文档提到的并不是这个JavaFX的JavaBeans架构。只是在这里介绍一下(使用JavaFX属性和绑定),但没有关于它的必要的。

More details.
The API documentation mentions not so much about this JavaFX's JavaBeans architecture. Just an introduction about it here (Using JavaFX Properties and Binding) but again nothing about its necessity.

所以我们挖一些源代码! :)

直接地,我们开始研究 FXMLLoader代码。我们注意到绑定表达式的前缀为

So lets dig some source code! :)
Straightforwardly, we start to look into FXMLLoader code first. We notice prefix for binding expression as

public static final String BINDING_EXPRESSION_PREFIX = "${";

进一步在第279行FXMLLoader确定 if(isBindingExpression(value))然后创建绑定,实例化 BeanAdapter 并获取propertyModel:

Further at line 279 FXMLLoader determines if (isBindingExpression(value)) then to create binding, instantiates BeanAdapter and gets propertyModel:

BeanAdapter targetAdapter = new BeanAdapter(this.value);
ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);

如果我们研究 BeanAdapter #getPropertyModel ()

public <T> ObservableValue<T> getPropertyModel(String key) {
    if (key == null) {
        throw new NullPointerException();
    }
    return (ObservableValue<T>)get(key + BeanAdapter.PROPERTY_SUFFIX);
}

它委托给 BeanAdapter#get() code>追加 String PROPERTY_SUFFIX =Property;

在get()方法中,简单的getter(counterProperty或getCounter或isCounter)通过反射调用,返回结果。如果getter不存在,则返回null。换句话说,如果JavaBean中不存在counterProperty(),则返回null。在这种情况下,由于FXMLLoader中的语句 if(propertyModel instanceof Property<?>),不执行绑定。因此,没有counterProperty()方法没有绑定。

it delegates to BeanAdapter#get() after appending String PROPERTY_SUFFIX = "Property";
In the get() method, simply the getter (either counterProperty or getCounter or isCounter) invoked by reflection, returning the result back. If the getter does not exist null returned back. In other words, if the "counterProperty()" does not exist in JavaBean, null returned back in our case. In this case the binding is not performed due to the statement if (propertyModel instanceof Property<?>) in FXMLLoader. As a result, no "counterProperty()" method no bindings.

如果bean中没有定义getter,会发生什么?再次从 BeanAdapter#get()代码,我们可以说,如果找不到getCounter(),则返回null,调用者将其忽略为无操作imo。

What happens if the getter is not defined in the bean? Again from the BeanAdapter#get() code we can say that if the "getCounter()" cannot be found the null returned back and the caller just ignores it as no-op imo.

这篇关于将Label的文本属性(在FXML文件中)绑定到IntegerProperty(在控制器中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆