滚动时带有RadioButtons的JavaFX TreeView显示不正确的状态

时间:2018-12-17 14:17:50

标签: javafx radio-button treeview

我需要一个TreeView,其中某些元素具有RadioButton。 因此,我环顾四周,使用了here中的一些代码,并在其中提出了一些自己的想法。

因此,结果是一个类(RadioTreeView)扩展了TreeView和自定义TreeItemTreeCell的类。

除了一件重要的事情,一切都很好:

在选择了一个TreeView的情况下滚动浏览RadioButton时,似乎会选择其他按钮。 此gif演示了问题。(滚动时我没有点击任何地方)

Short Video

通过一些调试,我发现ToggleGroup selectedItem 属性(由RadioButton中的所有TreeView共享),实际上永远不会改变。 而且,当我向每个RadioButton selected -Property添加一个侦听器时,它们都不会触发。

这让我感到困惑和疑惑,这是JavaFX错误还是我遗漏了一些非常明显的东西。

这是我的代码:

import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.util.Callback;

public class RadioTreeView<T> extends TreeView<T> {
    private ToggleGroup toggleGroup; // shared by all radioButtons

    public RadioTreeView() {
        super();
        toggleGroup = new ToggleGroup();

        setCellFactory(new Callback<TreeView<T>, TreeCell<T>>() {
            @Override
            public TreeCell<T> call(TreeView<T> param) {
                return new RadioTreeCell<T>(toggleGroup);
            }
        });

    }

    public static class RadioTreeItem<T> extends TreeItem<T> {
        private final boolean hasRadio; // defines whether a RadioButton should be shown

        public RadioTreeItem(boolean hasRadio, T item) {
            super(item);
            this.hasRadio = hasRadio;
        }

        public boolean getHasRadio() {
            return hasRadio;
        }
    }

    public static class RadioTreeCell<T> extends TreeCell<T> {
        private final RadioTreeButton<T> radio = new RadioTreeButton<T>();
        private final ToggleGroup toggleGroup;

        public RadioTreeCell(ToggleGroup toggleGroup) {
            super();
            this.toggleGroup = toggleGroup;
        }

        {
            setContentDisplay(ContentDisplay.LEFT);
        }

        @Override
        public void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);

            if (!empty && item != null) {
                setText(item.toString());
                if (((RadioTreeItem<T>) getTreeItem()).getHasRadio()) { // display radioButton as graphic
                    setGraphic(radio);
                    radio.setToggleGroup(toggleGroup);
                } else {
                    setGraphic(null);
                }
            } else {
                setGraphic(null);
                setText(null);
            }
        }
    }

    private static class RadioTreeButton<T> extends RadioButton {
        // non-important methods removed

        public RadioTreeButton() {
        }
    }

我们非常感谢您的帮助。

PS:我知道我的代码并不完美

1 个答案:

答案 0 :(得分:1)

TreeCell被重用。这意味着单个RadioButton可以用于包含不同TreeItem的单元中。您永远不会基于该项目更新单元格中RadioButton的选择状态。这将导致其余RadioButton被选中。滚动时,会将不同的TreeItem放入不同的单元格中。 TableCell的文本已更新,但RadioButton的选择状态未更新。

您需要以某种方式存储所选的TreeItem,例如使用userData的{​​{1}}属性:

ToggleGroup