JavaFx ComboBox绑定混乱 [英] JavaFx ComboBox binding confusion

查看:135
本文介绍了JavaFx ComboBox绑定混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个I18N实现,它通过属性绑定JavaFX UI元素,例如:

I have an I18N implementation that binds JavaFX UI elements through properties, for e.g.:

def translateLabel(l: Label, key: String, args: Any*): Unit =
    l.textProperty().bind(createStringBinding(key, args))

具有属性绑定很容易,并且效果很好.但是,我对ComboBox感到困惑,因为它需要一个ObservableList(在我的情况下为String),而且我不知道如何将我的翻译器功能绑定到该列表.我对ObservableValueObservableListProperty接口之间的区别感到矛盾,因为它们听起来都一样.

Having a property binding is easy and works well. However I struggle with ComboBox as it takes an ObservableList (of Strings in my case) and I have no idea how to bind my translator functions to that. I am conflicted about the difference between ObservableValue, ObservableList and Property interfaces as they all sound the same.

它具有itemsProperty()valueProperty(),但是缺少这些文件的文档且含糊不清,因此我不确定它们可以在哪里使用.

It has itemsProperty() and valueProperty() however the documentation for these is lacking and vague so I am not sure where they can be used.

我想做的是有一个ComboBox,其中所有元素(或至少选定的/可见的)都像属性一样动态地更改语言(I18N),就像绑定语言一样.

What I want to do is have a ComboBox where all elements (or at least the selected / visible one) changes the language dynamically (I18N) as if it was bound, just like a property.

为了更容易理解,我当前的实现是:

Just to make it easier understand, my current implementation is:

private def setAggregatorComboBox(a: Any): Unit = {

    val items: ObservableList[String] = FXCollections.observableArrayList(
        noneOptionText.getValue,
        "COUNT()",
        "AVG()",
        "SUM()"
    )

    measureAggregatorComboBox.getItems.clear()

    measureAggregatorComboBox.getItems.addAll(items)
}

noneOptionText是已经绑定到StringBindingStringProperty,而StringBinding是在类实例化时以这种方式转换的:

Where noneOptionText is a StringProperty that's already bound to a StringBinding that's translated upon class instantiation in this manner:

def translateString(sp: StringProperty, key: String, args: Any*): Unit =
        sp.bind(createStringBinding(key, args))

推荐答案

itemsProperty() valueProperty()选中的项(如果组合框是可编辑的,则为用户输入的值).

The valueProperty() is the selected item (or the value input by the user if the combo box is editable).

我建议您将组合框中的 data 作为键的列表,并使用自定义单元格将每个单元格中的文本绑定到这些键的翻译中.我不会讲scala,但是在Java中看起来像这样:

What I'd recommend is to have the data in the combo box be the list of keys, and use custom cells to bind the text in each cell to the translation of those keys. I don't speak scala, but in Java it looks like:

ComboBox<String> comboBox = new ComboBox<>();
comboBox.getItems().setAll(getAllKeys());

class TranslationCell extends ListCell<String> {

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        textProperty().unbind();
        if (empty || item == null) {
            setText("");
        } else {
            textProperty().bind(createStringBinding(item));
        }
    }
}

comboBox.setCellFactory(lv -> new TranslationCell());
comboBox.setButtonCell(new TranslationCell());

现在请注意,valueProperty()包含所选值的.

Note now that the valueProperty() contains the key for the selected value.

如果您确实想将项目绑定到ObservableValue<ObservableList<String>>,则可以执行以下操作:

If you really want to bind the items to an ObservableValue<ObservableList<String>> you can do something like:

comboBox.itemsProperty().bind(Bindings.createObjectBinding(() ->
    FXCollections.observableArrayList(...),
    ...));

其中第一个...是一个String值的变量,而第二个...是一个可观察的值,其中的更改将提示重新计算列表. (因此,在您的情况下,我猜您在某个位置代表当前语言环境的ObservableValue<Locale>;您将使用它作为第二个参数.)

where the first ... is a varargs of String values, and the second ... is an observable value, changes in which would prompt the list to be recomputed. (So in your case, I'm guessing you have an ObservableValue<Locale> somewhere representing the current locale; you would use that for the second argument.)

在您的特定用例(仅列表的第一个元素可国际化)的情况下,仅使用侦听器可能会更容易:

In your specific use case (where only the first element of the list is internationalizable), it might be easier simply to use a listener:

comboBox.getItems().setAll(
    noneOptionTest.getValue(), 
    "COUNT()",
    "AVG()",
    "SUM");
noneOptionTest.addListener((obs, oldVal, newVal) ->
    comboBox.getItems().set(0, newVal));

尽管我同意这不太优雅.

though I agree this is slightly less elegant.

出于完整性考虑:

我对ObservableValue之间的区别感到矛盾, ObservableListProperty接口听起来都一样.

I am conflicted about the difference between ObservableValue, ObservableList and Property interfaces as they all sound the same.

ObservableValue<T>:表示类型为T的单个值,可以观察(表示代码更改时可以执行).

ObservableValue<T>: represents a single value of type T which can be observed (meaning that code can be executed when it changes).

Property<T>:表示可写 ObservableValue<T>;目的是实现将具有代表该值的实际变量.它定义了其他功能,允许其值绑定到其他ObservableValue<T>.

Property<T>: represents a writable ObservableValue<T>; the intention is that implementations would have an actual variable representing the value. It defines additional functionality allowing its value to be bound to other ObservableValue<T>.

例如,

DoubleProperty x = new SimpleDoubleProperty(6);
DoubleProperty y = new SimpleDoubleProperty(9);
ObservableValue<Number> product = x.multiply(y);

xy都是Property<Number>; SimpleDoubleProperty的实现有一个表示该值的实际double变量,您可以执行y.set(7);之类的操作来更改该值.

x and y are both Property<Number>; the implementation of SimpleDoubleProperty has an actual double variable representing this value, and you can do things like y.set(7); to change the value.

另一方面,product不是Property<Number>;您无法更改其值(因为这样做会违反 binding :声明为product.getValue() == x.getValue() * y.getValue()的不变式);但是它是可观察的,因此您可以绑定到它:

On the other hand, product is not a Property<Number>; you can't change its value (because doing so would violate the binding: the declared invariant that product.getValue() == x.getValue() * y.getValue()); however it is observable, so you can bind to it:

BooleanProperty answerCorrect = new SimpleBooleanProperty();
answerCorrect.bind(product.isEqualTo(42));

ObservableList有所不同:它是一个java.util.List(元素的集合),您可以观察到它对列表上的操作进行响应. IE.如果将侦听器添加到ObservableList,则侦听器可以确定是否添加或删除了元素等.

An ObservableList is somewhat different: it is a java.util.List (a collection of elements), and you can observe it to respond to operations on the list. I.e. if you add a listener to an ObservableList, the listener can determine if elements were added or removed, etc.

这篇关于JavaFx ComboBox绑定混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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