Binding JavaFX绑定设置器约定
我知道Java和C,但属性绑定我只知道C MVVM。 我试图理解JavaFX中的属性绑定,并为属性值定制getter和setter,如在C中 我创建了以下类:Binding JavaFX绑定设置器约定,binding,javafx,javabeans,Binding,Javafx,Javabeans,我知道Java和C,但属性绑定我只知道C MVVM。 我试图理解JavaFX中的属性绑定,并为属性值定制getter和setter,如在C中 我创建了以下类: public class ViewModel { private StringProperty name; public ViewModel() { name = new SimpleStringProperty(); } public final String getName() {
public class ViewModel {
private StringProperty name;
public ViewModel() {
name = new SimpleStringProperty();
}
public final String getName() {
return name.get();
}
public final void setName(String name) {
this.name.set(name);
}
public StringProperty getNameProperty() {
return name;
}
}
public class Controller implements Initializable {
@FXML
private TextField nameField;
private final ViewModel viewModel;
public Controller() {
viewModel = new ViewModel();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Bindings.bindBidirectional(nameField.textProperty(),
viewModel.getNameProperty());
}
}
我的印象是,如果我遵循推荐的JavaBean/JavaFX命名约定,那么绑定系统将足够聪明,可以使用反射并为属性使用自定义的getter/setter。但是我的视图模型getter/setter从未被使用过
相反,绑定直接使用属性的get/set方法,而无需我的交互。
我读到我可以使用以下代码,但必须有比这更好的方法:
name = new SimpleStringProperty() {
@Override public void set(String value) {
// do something...
super.set(value);
}
};
我可以指定绑定应该使用哪些方法来获取/设置我的属性吗?
另一方面,我如何在不必更改的情况下,在C中通知属性已更改NotifyOfPropertyChange
编辑:
我试图做的是对最终设置到我的属性的内容进行更多的选择,因为我希望稍后使用它的值来填充这里省略的数据模型
在C语言中,这很简单,我只是在setter中设置了一个谓词。我可以通过设置其他属性来推动表单/向导的进度
public String Property {
get { return _property; }
set {
if(SomePredicate(value)) {
_property = value;
_nextButtonCommand.canExecute() = true;
// notify...
}
}
}
JavaFX属性
在ViewModel类中定义name属性的约定是:
public class ViewModel {
private StringProperty name;
public ViewModel() {
// parameters are owning bean, property name, and initial value,
// and are optional for the property convention
name = new SimpleStringProperty(this, "name", "");
}
public final String getName() {
return name.get();
}
public final void setName(String name) {
this.name.set(name);
}
// Note this method name:
public final StringProperty nameProperty() {
return name;
}
}
有一些变体:特别是如果您想使事物可重写,可以从nameProperty中删除最后一个修饰符,并在get和set方法中将this.name替换为this.nameProperty。关键是要确保调用setName。。。总是给出与nameProperty.set相同的结果。。。对于get方法也是如此
我认为你的一般解释有点偏离了一个层次,如果这有意义的话。该类定义了get和set方法,这些方法将因绑定而自动调用。因此,即使您有一个稍微不标准的命名约定,在文本字段中键入仍然会更新属性值。绑定API没有太多使用?据我所知,反射只是用属性注册监听器,并在另一个监听器发生变化时进行更新
至于自定义getter和setter,您展示的重写技术实际上只支持属性类。但是,我从来没有找到一个好的使用案例,尤其是绑定API,它让您有机会非常轻松地创建依赖值
更新
因此,对于您的具体示例,我将按照以下思路实现它:
public class ViewModel {
private StringProperty name = new SimpleStringProperty(this, "name");
// usual JavaFX Property methods...
}
然后,无论你在哪里需要它:
Predicate<String> predicate = ... ;
BooleanBinding canExecute = Bindings.createBooleanBinding(() ->
predicate.test(viewModel.getName()),
viewModel.nameProperty());
如果谓词可能改变,您甚至可以这样做
ObjectProperty<Predicate<String>> predicate = new SimpleObjectProperty<>(s -> true);
BooleanBinding canExecute = Bindings.createBooleanBinding(() ->
predicate.get().test(viewModel.getName()),
predicate, viewModel.nameProperty());
或者,在Java8中,要简洁得多
viewModel.nameProperty().addListener((obs, oldName, newName) ->
System.out.println("Name changed from "+oldValue+" to "+newValue));
只有当您有一个依赖于计算的ObservalEvalue时,无效侦听器和更改侦听器之间的差异才会变得明显。比较:
IntegerProperty x = new SimpleIntegerProperty(2);
IntegerProperty y = new SimpleIntegerProperty(3);
ObservableNumberValue sum = x.add(y);
sum.addListener(obs -> System.out.println("Invalidated")); // invalidation listener
x.set(3);
y.set(5);
使用相同的代码,但使用更改侦听器:
sum.addListener((obs, oldSum, newSum) -> System.out.println("Changed"));
而不是无效侦听器
更多详细信息请参见。JavaFX属性
在ViewModel类中定义name属性的约定是:
public class ViewModel {
private StringProperty name;
public ViewModel() {
// parameters are owning bean, property name, and initial value,
// and are optional for the property convention
name = new SimpleStringProperty(this, "name", "");
}
public final String getName() {
return name.get();
}
public final void setName(String name) {
this.name.set(name);
}
// Note this method name:
public final StringProperty nameProperty() {
return name;
}
}
有一些变体:特别是如果您想使事物可重写,可以从nameProperty中删除最后一个修饰符,并在get和set方法中将this.name替换为this.nameProperty。关键是要确保调用setName。。。总是给出与nameProperty.set相同的结果。。。对于get方法也是如此
我认为你的一般解释有点偏离了一个层次,如果这有意义的话。该类定义了get和set方法,这些方法将因绑定而自动调用。因此,即使您有一个稍微不标准的命名约定,在文本字段中键入仍然会更新属性值。绑定API没有太多使用?据我所知,反射只是用属性注册监听器,并在另一个监听器发生变化时进行更新
至于自定义getter和setter,您展示的重写技术实际上只支持属性类。但是,我从来没有找到一个好的使用案例,尤其是绑定API,它让您有机会非常轻松地创建依赖值
更新
因此,对于您的具体示例,我将按照以下思路实现它:
public class ViewModel {
private StringProperty name = new SimpleStringProperty(this, "name");
// usual JavaFX Property methods...
}
然后,无论你在哪里需要它:
Predicate<String> predicate = ... ;
BooleanBinding canExecute = Bindings.createBooleanBinding(() ->
predicate.test(viewModel.getName()),
viewModel.nameProperty());
如果谓词可能改变,您甚至可以这样做
ObjectProperty<Predicate<String>> predicate = new SimpleObjectProperty<>(s -> true);
BooleanBinding canExecute = Bindings.createBooleanBinding(() ->
predicate.get().test(viewModel.getName()),
predicate, viewModel.nameProperty());
或者,在Java8中,要简洁得多
viewModel.nameProperty().addListener((obs, oldName, newName) ->
System.out.println("Name changed from "+oldValue+" to "+newValue));
只有当您有一个依赖于计算的ObservalEvalue时,无效侦听器和更改侦听器之间的差异才会变得明显。比较:
IntegerProperty x = new SimpleIntegerProperty(2);
IntegerProperty y = new SimpleIntegerProperty(3);
ObservableNumberValue sum = x.add(y);
sum.addListener(obs -> System.out.println("Invalidated")); // invalidation listener
x.set(3);
y.set(5);
使用相同的代码,但使用更改侦听器:
sum.addListener((obs, oldSum, newSum) -> System.out.println("Changed"));
而不是无效侦听器
.更新的答案中有更多详细信息,以响应编辑。我实际上喜欢覆盖属性集。说真的
在我的代码中,当我按照下面的答案执行时,setter永远不会被调用。我只使用FXML和我的模型来完成我的整个应用程序,但是我的控制器没有任何代码落后。更新答案以响应编辑。我实际上喜欢覆盖属性集。在我的代码中,由于某种原因,当我按照下面的答案执行时,setter从未被调用。我只使用FXML来完成我的整个应用程序,而我的控制器没有代码落后。