2009-03-19 13 views
0

私は、各ノードの隣にあるチェックボックスを備えたツリーコントロールを持っています。このチェックボックスを使うと、ノード上のチェックされた状態、チェックされていない状態、および中央のチェックされた状態が可能になります。ノードをクリックすると、親と子が更新されます。私が見つけたコードでは、トリックはビットシフトを使用しており、正確に何が起こっているのかを理解しようとしています。誰かがこのビット操作コードを説明できますか?

誰かが次のコードを説明できますか?または、このコードを書き直して理解しやすくしてください。

// click event handler 
private function eventMessageTree_itemCheckHandler(event:TreeEvent):void { 
    var node:ITreeNode = ITreeNode(event.item); 
    var checkState:uint = TreecheckboxItemRenderer(event.itemRenderer).checkBox.checkState; 
    updateParents(node, checkState); 
    updateChilds(node, checkState); 
} 

private function updateChilds(item:ITreeNode, value:uint):void { 
    var middle:Boolean = (value & 2 << 1) == (2 << 1); 
    var selected:Boolean = (value & 1 << 1) == (1 << 1); 

    if (item.children.length > 0 && !middle) { 
    for each (var childNode:ITreeNode in item.children)  { 
     childNode.checked = value == (1 << 1 | 2 << 1) ? "2" : value == (1 << 1) ? "1" : "0"; 
     updateChilds(childNode, value); 
    } 
    } 
} 

private function updateParents(item:ITreeNode, value:uint): void { 
    var checkValue:String = (value == (1 << 1 | 2 << 1) ? "2" : value == (1 << 1) ? "1" : "0"); 
    var parentNode:ITreeNode = item.parent; 
    if (parentNode) { 
    for each (var childNode:ITreeNode in parentNode.children) { 
     if (childNode.checked != checkValue) { 
     checkValue = "2"; 
     } 
    } 
    parentNode.checked = checkValue; 
    updateParents(parentNode, value); 
    }  
} 

答えて

1

基本的には、このような式:

var middle:Boolean = (value & 2 << 1) == (2 << 1); 

は直感的です。通常、定数1を左にシフトすることでビットをテストします。これは、シフトされたビット数をビットのインデックスと同じにし、LSB(右端)ビットをビット番号0としてカウントするためです。

また、 ==比較で結果をテストしても意味がありません。なぜなら、常に0または非ゼロになるからです。少なくとも、あなたの言語が必要とするならば、もっと簡単なものをテストすることができます。

デフォルトでは、ゼロ以外の整数を「真」と解釈するため、比較は完全に不要で、クラッタ、繰り返しを導入し、バグのリスクを高めるだけです。

私はそうのようにこれを記述します

var middle:Boolean = (value & (1 << 2)) != 0; 

余分な括弧は、物事がグループ化されているどのようにそれをより明確に役立つはずです。 「2 < < 1」は「1 < < 2」と書き換えられました。これは単に「スイッチ」だけではなく、同じビット値を得るために適切なシフトを計算する必要があります(この場合は4)。

もちろん、ビットテストをサブルーチンに入れて呼び出して、コードを読みやすくすることができます。

+0

感謝を。だから私が正しく理解すれば、私はちょうど1 << 2か2 << 1を4で置き換えることができますか?定数4の代わりにビットシフトを使用することに利点がありますか? –

+0

利点はありません。また、(1 << 1 | 2 << 1)を6に置き換えることもできます。可読性の観点からは、おそらく元のものと同じくらい悪いですが、少なくともそれは短いです。 UNCHECKED = 1 << UNCHECKED = 1の代わりにUNCHECKED = 4のようなconstを宣言すると、両方のオペランドをハードコーディングするだけで意味があります。 –

2

制御におけるにcheckStateの値は、1,2、または4のいずれかとすることができるように見えます(あるいは0,2、および4):

public static const CONTROL_UNCHECKED:uint = 1; // not checked, and some descendants are 
public static const CONTROL_CHECKED:uint = 2; // checked, and all descendants are 
public static const CONTROL_MIDDLE:uint = 4; // not checked, but some descendants are 

ノードにおけるチェック値がすることができるが0,1,2のいずれか:

public static const UNCHECKED:uint = 0; // not checked, and some descendants are 
public static const CHECKED:uint = 1; // checked, and all descendants are 
public static const MIDDLE:uint = 2; // not checked, but some descendants are 

これは本当に混乱しています。理想的には、これらは同じ定数のセットになります。

更新するには:あなたの答えのための

private function controlStateToNodeState(value:uint):uint { 
    return value/2; 
} 
    ... 
    updateParents(node, controlStateToNodeState(checkState)); 
    updateChilds(node, controlStateToNodeState(checkState)); 
    ... 

/** Updates the descendants of the node based on state: 
* If value is CHECKED, all children are CHECKED 
* If value is UNCHECKED, all children are UNCHECKED 
* If value is MIDDLE, children are left alone 
*/ 
private function updateChilds(item:ITreeNode, value:uint):void { 
    if (value == MIDDLE) { 
     return; // if value is MIDDLE, children are left alone 
    } 

    // not middle, so update all children to my state 
    for each (var childNode:ITreeNode in item.children)  { 
     childNode.checked = value; 
     updateChilds(childNode, value); 
    } 
    } 
} 

/** 
* Updates the ancestor nodes based on state: 
* If value is CHECKED, ancestors are made MIDDLE if not already checked 
* If value is MIDDLE, ancestors are made middle (they should not already be CHECKED) 
*/ 
private function updateParents(item:ITreeNode, value:uint): void { 
    ... 
} 
関連する問題