5

我面临的问题是,CheckboxTreeViewer在 Linux Debian 上实现了完美的工作,但在 Windows 下却没有。首先,我不理解“setGrayed()”的概念。是否表明,只有元素中的部分子元素被选中?

所以问题是:当我在 Windows 下检查一个项目时,它会检查树中的所有其他元素。不知何故,整个逻辑被忽略了。

这是我的代码ICheckStateListener

@Override
public void checkStateChanged(final CheckStateChangedEvent event) {
    // object checked
    final TreePath path = ((ITreeSelection) this.treeViewer.getSelection()).getPaths()[0];
    checkChildren(path, event.getChecked());
    checkParents(path.getParentPath());
    syncData();
}

public void checkParents(final TreePath path) {
    if (path == null) {
        return;
    }
    final IFieldElement<Object> treeElement = (IFieldElement<Object>) path.getLastSegment();
    if (treeElement != null) {
        boolean allChecked = true;
        boolean allUnchecked = true;
        for (final Object fieldElement : treeElement.getChildrenElements()) {
            allChecked = allChecked && this.treeViewer.getChecked(fieldElement);
            allUnchecked = allUnchecked && !this.treeViewer.getChecked(fieldElement);
        }
        if (allUnchecked) {
            this.treeViewer.setChecked(treeElement, false);
            this.treeViewer.setGrayed(treeElement, false);
        } else
        if (allChecked) {
            this.treeViewer.setChecked(treeElement, true);
            this.treeViewer.setGrayed(treeElement, false);
        } else
        if (!allUnchecked && !allChecked) {
            this.treeViewer.setChecked(treeElement, true);
            this.treeViewer.setGrayed(treeElement, true);
        }
    }
    checkParents(path.getParentPath());
}

public void checkChildren(final TreePath path, final boolean checked) {
    if (path == null) {
        return;
    }
    final Object element = path.getLastSegment();
    if (element != null) {
        this.treeViewer.setChecked(element, checked);
        this.treeViewer.setGrayed(element, false);
        this.treeViewer.setSubtreeChecked(element, checked);
        if (element instanceof EventMethod) {
            checkEventMethod(path, element, checked);
        }

    }
}

编辑:我正在使用 Eclipse Indigo

提前致谢!

4

2 回答 2

7

树中复选框的“灰色”状态只是另一种状态,除了选中和未选中。你如何使用它取决于你,但通常它意味着“部分检查”状态。在通常的实践中,如果一个项目有一些子项被选中而另一些未被选中,则父项将显示选中+灰色状态。具体如何呈现取决于操作系统及其版本。在一些实现中,用户只能选中或取消选中树项,并且不能通过鼠标点击显式地设置项的灰色状态。它会根据选中的孩子自动发生。但是,有时有些应用程序还允许您单击复选框以将其选中为灰色到未选中。在这种情况下,灰色状态通常意味着“默认”状态。无论如何,这取决于实现。

我不确定您所面临的问题是什么,但如果我不得不猜测,我会说小部件在 Debian 与 Windows 中在抛出事件时表现不同。因为在您的实现中,每当检查一个项目时,您都会检查它的所有父项及其所有子项,因此可能是treeViewer.setChecked()在 Windows 中调用父项也开始引发事件,并且您的侦听器被调用以检查所有父项的所有子项,因此一切都被启用。测试一下,看看这是否是问题所在。为避免这种情况,请在修改任何内容之前第一次收到事件时设置一个标志。并且在修改时忽略所有checkStateChanged()只要设置了该标志,事件就会调用,以便您对元素的更改不会递归地应用于整个树。一旦您对一项选中/未选中操作的操作完成,重置标志,以便可以再次处理用户事件。

private boolean ignoreCheckEvent = false;

@Override
public void checkStateChanged(final CheckStateChangedEvent event) {
    if (ignoreCheckEvent)
        return;

    ignoreCheckEvent = true;

    try {
        // object checked
        final TreePath path = ((ITreeSelection) this.treeViewer.getSelection()).getPaths()[0];
        checkChildren(path, event.getChecked());
        checkParents(path.getParentPath());
        syncData();
    }
    finally {
        ignoreCheckEvent = false;
    }
}
于 2013-01-18T15:50:39.587 回答
1

尝试使用 org.eclipse.ui.dialogs.ContainerCheckedTreeViewer

描述:在容器(非叶)节点上具有选中/灰色状态的特殊行为的 CheckboxTreeViewer:灰色状态用于可视化其子节点的选中状态。如果检查了所有包含的叶子,则检查容器并且非灰色。如果检查了一些但不是所有的叶子,则容器是灰色的。

于 2019-07-12T07:00:42.063 回答