如何处理相关的FX属性?

编程入门 行业动态 更新时间:2024-10-26 13:27:37
本文介绍了如何处理相关的FX属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

属性-ol'风格的Bean属性与闪烁的fx属性相同-如果它们彼此正交,则效果最佳.如果它们之间存在某种联系,它们就会带来问题-还是两种类型.在讨厌的真实世界中,发生这种情况的频率可能比我们希望的高.

作为一个例子,使用两个选定的selectedIndex/selectedItem:如果索引包含列表中的项,则索引指向该项的位置;如果不包含索引,则指向项的负数.更新一个也需要更新另一个.

对于Java Bean,解决方案是简单,因为Bean本身对何时触发更改具有完全控制权.而对于fx bean?

SelectionModel中使用的基本模式

Property<T> theRealItemProperty = new SimpleObjectProperty<>(); ReadOnlyProperty<T> readOnlyItemProperty = new ReadOnlyObjectProperty(theRealItemProperty); /** * Public access is read-only */ public final ReadOnlyProperty<T> itemProperty() { return readOnlyItemProperty; } /** * Setting allowed for subclasses only (and mis-behaving package neighbors ;-) */ protected final void setItem(T item) { theRealItemProperty.set(item); } /** * Special setting api for general public */ public void select(T item) { setIndex(indexOf(item)); setItem(item); }

属性在调用其setter时触发,bean没有控制权.由于这些调用之间的内部状态不稳定,因此第一个侦听器的侦听器在接收到通知后不得访问第二个侦听器..由于他们不知道哪个触发了第一个,因此他们永远无法依赖Bean保持稳定. >

现在该怎么办?在拥有bean的地方还是在客户端?不知何故推迟了大火?绝妙的Platform.runLater()散布在所有应用程序代码中吗?陷入困境..

解决方案

根据James_D的建议, ReactFX 'InhiBeans 来了.

从头开始编写bean时,请使用该包提供的属性-它们扩展了核心类,具有相同的名称,因此与交换导入一样简单.然后保护修改方法,例如:

public void select(T item) { Guard guard = Guard.multi(theRealItemProperty.guard(), theRealIndexProperty.guard()); setIndex(indexOf(item)); setItem(item); guard.close(); }

当子类化最终确定其相关属性的核心类时,一个选择可能会变得肮脏:通过反射将其替换.一个例子是 AbstractSelectionModelBase ,目前是我实验中的基本MultipleSelectionModel

// going dirty: replace super's selectedItem/Index property // with guarded cousins itemReplacement = new ReadOnlyObjectWrapper<>(this, "selectedItem"); replaceField("selectedItem", itemReplacement); indexReplacement = new ReadOnlyIntegerWrapper(this, "selectedIndex", -1); replaceField("selectedIndex", indexReplacement); // usage in methods that update single selection state protected void syncSingleSelectionState(int selectedIndex) { Guard guard = Guard.multi(itemReplacement.guard(), indexReplacement.guard()); setSelectedIndex(selectedIndex); if (selectedIndex > -1) { setSelectedItem(getModelItem(selectedIndex)); } else { // PENDING JW: do better? can be uncontained item setSelectedItem(null); } guard.close(); focus(selectedIndex); }

在核心中拥有(并使用它)这样的功能会很酷.

Properties - ol' style bean properties just the same as blinky fx properties - work best if they are orthogonal to each other. They pose problems - again, both types - if they are somehow correlated. Which might happen in nasty Real World more often than we like.

As an example take the twosome selectedIndex/selectedItem: the index points to the position of the item in a list if it is contained, or is negative if not. Updating one requires to update the other as well.

For java beans, the solution is straightforward because the bean itself has full control about when to fire the changes. And for fx beans?

A base pattern used in SelectionModel

Property<T> theRealItemProperty = new SimpleObjectProperty<>(); ReadOnlyProperty<T> readOnlyItemProperty = new ReadOnlyObjectProperty(theRealItemProperty); /** * Public access is read-only */ public final ReadOnlyProperty<T> itemProperty() { return readOnlyItemProperty; } /** * Setting allowed for subclasses only (and mis-behaving package neighbors ;-) */ protected final void setItem(T item) { theRealItemProperty.set(item); } /** * Special setting api for general public */ public void select(T item) { setIndex(indexOf(item)); setItem(item); }

The properties fire at the time of calling their setters, the bean has no control. As internal state is unstable between those calls, listeners to the first must not access the second on receiving the notification .. as they can’t know which is the first to fire, they cannot rely on the bean being stable, ever.

What to do now, either on owning bean or client side? Somehow defer the fire? The ol' trick Platform.runLater() scattered all over application code? Stumped ..

解决方案

As suggested by James_D, ReactFX' InhiBeans come to the rescue.

When coding a bean from scratch, use the properties provided by that package - they extend core classes, have the same names so its as simple as exchanging the imports. Then guard modifying methods like:

public void select(T item) { Guard guard = Guard.multi(theRealItemProperty.guard(), theRealIndexProperty.guard()); setIndex(indexOf(item)); setItem(item); guard.close(); }

When subclassing core classes that finalized their correlated properties an option might be to go dirty: replace them via reflection. An example is AbstractSelectionModelBase which currently is the base MultipleSelectionModel in my experiments

// going dirty: replace super's selectedItem/Index property // with guarded cousins itemReplacement = new ReadOnlyObjectWrapper<>(this, "selectedItem"); replaceField("selectedItem", itemReplacement); indexReplacement = new ReadOnlyIntegerWrapper(this, "selectedIndex", -1); replaceField("selectedIndex", indexReplacement); // usage in methods that update single selection state protected void syncSingleSelectionState(int selectedIndex) { Guard guard = Guard.multi(itemReplacement.guard(), indexReplacement.guard()); setSelectedIndex(selectedIndex); if (selectedIndex > -1) { setSelectedItem(getModelItem(selectedIndex)); } else { // PENDING JW: do better? can be uncontained item setSelectedItem(null); } guard.close(); focus(selectedIndex); }

Would be cool to have (and use it!) such a feature in core.

更多推荐

如何处理相关的FX属性?

本文发布于:2023-11-25 14:20:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1630101.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何处理   属性   FX

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!