在使用JFace的CheckboxTreeViewer做开发时,如果遇到如下问题:
- check状态点击出现问题,check A却让B的状态check了
- 置灰(setGrayed)某个元素,元素状态并没有置灰,而改成了checked
- 选中某个元素,在selection linstener中监听到的选中元素却不是选中的元素
- 。。。。
如果遇到上述一系列问题(或者其他比较反常的问题),那很有可能你的问题原因是:CheckboxTreeViewer的某一级树结构中含有重复元素。举例说明:
假如CheckboxTreeViewer的input为如下结构:
A
|__B //1
C
|__B //2
在选中 2 的时候,可能变化的是1的状态,或者出现其他异常问题。该问题出现根本原因是AbstractTreeViewer(CheckboxTreeViewer的父类)的一个Bug,有如下代码:
protected boolean isSameSelection(List items, Item[] current) {
// If they are not the same size then they are not equivalent
int n = items.size();
if (n != current.length) {
return false;
}
CustomHashtable itemSet = newHashtable(n * 2 + 1);
for (Iterator i = items.iterator(); i.hasNext();) {
Item item = (Item) i.next();
Object element = item.getData();
itemSet.put(element, element);
}
// Go through the items of the current collection
// If there is a mismatch return false
for (int i = 0; i < current.length; i++) {
if (current[i].getData() == null
|| !itemSet.containsKey(current[i].getData())) {
return false;
}
}
return true;
}
这段代码用来比较树上的元素是否相等,在比较时,只考虑本级目录,而未考虑父目录是否相同,一种改进方案是(摘抄自stackoverflow):
protected boolean isSameSelection(List items, Item[] current) {
// If they are not the same size then they are not equivalent
int n = items.size();
if (n != current.length) {
return false;
}
Set itemSet = new HashSet(n * 2 + 1);
for (Iterator i = items.iterator(); i.hasNext();) {
Item item = (Item) i.next();
itemSet.add(getTreePathFromItem(item));
}
// Go through the items of the current collection
// If there is a mismatch return false
for (int i = 0; i < current.length; i++) {
if (current[i].getData() == null
|| !itemSet.contains(getTreePathFromItem(current[i]))) {
return false;
}
}
return true;
}
在改进的代码中,将 对数据的判断改为了对路径的判断,用于解决元素重复这个问题。