如何正确使用CheckboxTreeViewer?

时间:2013-01-17 16:53:51

标签: java checkbox tree swt jface

我面临的问题是,实施的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

提前致谢!

2 个答案:

答案 0 :(得分:6)

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

我不确定你面临的问题是什么,但如果我不得不猜测我会说在推出活动时,小部件在Debian vs Windows中表现不同。由于在您的实现中每当检查一个项目时,您都会检查其所有父项及其所有子项,因此可能是在Windows中的父项上调用treeViewer.setChecked()也会开始抛出事件,并且会调用您的监听器来检查所有子项所有父母因此一切都得到启用。测试一下,看看这是不是问题。要避免这种情况,请创建一个标志,在首次接收事件之前设置该标志,然后再修改任并且修改忽略所有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;
    }
}

答案 1 :(得分:0)

尝试

org.eclipse.ui.dialogs.ContainerCheckedTreeViewer 
  

说明

     

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