JavaFX ChoiceBox 添加具有类型安全性的分隔符

tha*_*y09 5 javafx javafx-2 javafx-8

我希望在选择框中添加一个分隔符并仍然保留类型安全。

在我见过的所有示例中,他们只执行以下操作:

ChoiceBox<Object> cb =  new ChoiceBox<>();
cb.getItems().addAll("one", "two", new Separator(), "fadfadfasd", "afdafdsfas");
Run Code Online (Sandbox Code Playgroud)

有没有人想出一个解决方案来添加分隔符并仍然保持类型安全?

我希望如果我想添加分隔符,我应该能够执行以下操作:

ChoiceBox<T> cb = new ChoiceBox<T>();
cb.getSeparators().add(1, new Separator()); // 1 is the index of where the separator should be
Run Code Online (Sandbox Code Playgroud)

我不应该仅仅为了添加分隔符而牺牲类型安全。

kle*_*tra 1

如前所述,只有添加到项目(脏、脏)时才支持分隔符。为了按照问题中预期的方式支持他们,我们需要:

  • 将分隔符列表的概念添加到 choiceBox
  • 使其皮肤了解该列表

虽然前者没什么大不了的,但后者需要完全重写(主要是 c&p)其皮肤,因为所有内容都紧紧隐藏在隐私中。如果无论如何都发生了重写,那么只需多几行:-)

只是为了好玩,我正在尝试ChoiceBoxX,它解决了选择处理中的一些讨厌的错误,所以忍不住尝试一下。

首先,添加对 ChoiceBoxx 本身的支持:

/**
 * Adds a separator index to the list. The separator is inserted 
 * after the item with the same index. Client code
 * must keep this list in sync with the data.
 * 
 * @param separator
 */
public final void addSeparator(int separator) {
    if (separatorsList.getValue() == null) {
        separatorsList.setValue(FXCollections.observableArrayList());
    }
    separatorsList.getValue().add(separator);
};
Run Code Online (Sandbox Code Playgroud)

然后ChoiceBoxXSkin进行一些更改

  • 必须听separatorsList
  • 必须期待index-of-menuItem != index-of-choiceItem
  • menuItem 必须保留其选择索引

最简单的是,侦听器重新构建弹出窗口,menuItem 将 dataIndex 存储在其属性中,并且需要通过其 dataIndex 访问弹出窗口的所有代码都委托给一个方法,该方法循环遍历 menuItems 直到找到合适的方法:

protected RadioMenuItem getMenuItemFor(int dataIndex) {
    if (dataIndex < 0) return null;
    int loopIndex = dataIndex;
    while (loopIndex < popup.getItems().size()) {
        MenuItem item = popup.getItems().get(loopIndex);

        ObservableMap<Object, Object> properties = item.getProperties();
        Object object = properties.get("data-index");
        if ((object instanceof Integer) && dataIndex == (Integer) object) {
            return item instanceof RadioMenuItem ? (RadioMenuItem)item : null;
        }
        loopIndex++;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)