1
[ ]All1           [ ]All2        

[ ]checkbox1A     [ ]checkbox1B

[ ]checkbox2A     [ ]checkbox2B

上記のチャートに基づいて、いくつかのことを行う必要があります。

  1. すべてのチェックボックスは、それが存在する列のオン/オフにのみ影響し、その列のすべてのチェックボックスをオン/オフにします。
  2. すべてのチェックボックスはペアで機能するため、checkbox1A がオン/オフの場合、checkbox1B はオン/オフする必要があります
  3. [すべて] チェックボックスがオンになっていて、ユーザーが列の 1 つ以上のチェックボックスをオフにした場合、[すべて] チェックボックスはオフにする必要がありますが、既にオンになっているすべてのチェックボックスはオンのままにする必要があります。

つまり、これは連鎖反応のセットアップに似ています。チェックボックス All1 がオンの場合、chieckbox1A と 2A がオンになり、オンになっているため、checkbox1B と 2B もオンになりますが、チェックボックス All2 はオフのままです。このロジックに基づいて信号を接続してみましたが、対になったロジックだけが 100% 機能します。すべてのチェックボックスのロジックは 50% の確率でしか機能せず、正確ではありません。既にチェックされているすべてのチェックボックスをオフにしない限り、すべてのチェックボックスをオフにする方法はありません。

本当に本当に助けが必要です... TT

サンプルコード:

cbPairKeys = cbPairs.keys()
    for key in cbPairKeys:
        cbOne = cbPairs[key][0][0]
        cbTwo = cbPairs[key][1][0]
        cbOne.stateChanged.connect(self.syncCB)
        cbTwo.stateChanged.connect(self.syncCB)

def syncCB(self):               
    pairKeys = cbPairs.keys()
    for keys in pairKeys:
        cbOne = cbPairs[keys][0][0]
        cbOneAllCB = cbPairs[keys][0][4]
        cbTwo = cbPairs[keys][1][0]
        cbTwoAllCB = cbPairs[keys][1][4]

        if self.sender() == cbOne:
            if cbOne.isChecked() or cbTwoAllCB.isChecked():
                cbTwo.setChecked(True)
            else:
                cbTwo.setChecked(False)
        else:
            if cbTwo.isChecked() or cbOneAllCB.isChecked():
                cbOne.setChecked(True)
            else:
                cbOne.setChecked(False) 

編集

ユーザー Avaris の助けと忍耐のおかげで、私はコードをよりクリーンなものに削減し、1 番目と 2 番目の望ましい動作で 100% の時間動作することができました。

#Connect checkbox pairs     
cbPairKeys = cbPairs.keys()
    for key in cbPairKeys:
        cbOne = cbPairs[key][0][0]
        cbTwo = cbPairs[key][1][0]
        cbOne.toggled.connect(cbTwo.setChecked)
        cbTwo.toggled.connect(cbOne.setChecked) 

#Connect allCB and allRO signals    
cbsKeys = allCBList.keys()
    for keys in cbsKeys:
        for checkbox in allCBList[keys]:
            keys.toggled.connect(checkbox.setChecked)

ユーザーがモジュラーチェックボックスを選択的にオフにした場合にのみ、すべてのチェックボックスをオフにする必要があります

4

2 に答える 2

3

あなたのデータ構造を理解していれば、解決策があります。私が間違っている場合は訂正してください: allCBListis a dict(紛らわしい名前! :) )。そのキーはall*チェックボックスです。値allCBList[key]は、そのチェックlistボックスに関連付けられたallチェックボックス付きです。例の構造では、次のようになります。

{ All1 : [checkbox1A, checkbox1B],
  All2 : [checkbox2A, checkbox2B]}

次に、これが必要です。チェックボックスが切り替えられ、状態になっている場合、他のすべてのチェックボックスがchecked状態になっている場合は、チェックボックスをオンにする必要があります。それ以外の場合は、チェックが外されます。All*checked

for key, checkboxes in allCBList.iteritems():
    for checkbox in checkboxes:
        checkbox.toggled.connect(lambda checked, checkboxes=checkboxes, key=key: key.setChecked(checked and all(checkbox.isChecked() for checkbox in checkboxes))

このステートメントには少し説明が必要だと思います。

lambda checked, checkboxes=checkboxes, key=key:

lambdaシグナルに接続された callable を作成します。toggledチェックボックスのステータスを渡し、checked変数に渡されます。checkboxes=checkboxesandkey=keyパーツは、現在の値をラムダのパラメーターにcheckboxes渡します。key(これは s の閉鎖のために必要ですlambda)

次に来る:

key.setChecked(...)

適切なチェックボックスのchecked状態を設定しています。そして、この中に:keyAll*

checked and all(checkbox.isChecked() for checkbox in checkboxes)

allTrue内部のすべてがである場合は、すべての s の状態Trueをチェックします。checkboxそして、これはTrueすべてがそうである場合に戻りますchecked(つまり、isChecked()戻りますTrue)。

checked and ...ショートする部分がありallます。現在のチェックボックスがになっている場合は、unchecked他のチェックボックスをオンにする必要はありません。All*でしょうunchecked

( PS :ちなみに、キーを反復処理するため.keys()に aを取得する必要はありません。 を反復処理するだけで、その を反復処理します。)dictdictkeys

編集All*:サブチェックボックスをクリックしてチェックボックスを切り替える連鎖反応を避けるために、All*チェックボックスの信号をclickedではなく に変更する必要がありtoggledます。そのため、All*チェック ボックスは、ユーザー インタラクションの場合にのみ、その下にある他のものに影響を与えます。

最終的に、変更されたコードは次のようになります。

# Connect checkbox pairs
# you just use the values
# change 'itervalues' to 'values' if you are on Python 3.x
for cbPair in cbPairs.itervalues():
    cbOne = cbPair[0][0]
    cbTwo = cbPair[1][0]
    cbOne.toggled.connect(cbTwo.setChecked)
    cbTwo.toggled.connect(cbOne.setChecked) 

# Connect allCB and allRO signals
# change 'iteritems' to 'items' if you are on Python 3.x
for key, checkboxes in allCBList.iteritems():
    for checkbox in checkboxes:
        key.clicked.connect(checkbox.setChecked)
        checkbox.toggled.connect(lambda checked, checkboxes=checkboxes, key=key: key.setChecked(checked and all(checkbox.isChecked() for checkbox in checkboxes))
于 2012-09-12T02:01:43.170 に答える
0

あなたの問題は、チェックボックスがtoggled信号接続し、接続されたスロットの状態を切り替えているため、信号が再び放出され(スロットが再度実行される...)、予測できない結果が得られることです。明らかに、それはあなたが望んでいた行動ではありません。いくつかの方法で修正できます。

  • スロットの最初の信号を切断し、最後に再び接続することによって
  • 信号の再放出を制御する巧妙なコードを使用することによって (これは、Avari のコードが非常にコンパクトな方法で行うことだと思いますが、完全にはわかりません)
  • clickedチェックボックスの状態が変化しても再発行されないため、シグナルを使用する

どのアプローチに従うかはあなた次第です。次のコードでは、3 番目の方法を使用しています。

    self.cbPair = {}
    self.cbPair['0'] = (QtGui.QCheckBox('all1', parent), 
        QtGui.QCheckBox('all2', parent))
    self.cbPair['1'] = (QtGui.QCheckBox('1a', parent), 
        QtGui.QCheckBox('1b', parent))
    self.cbPair['2'] = (QtGui.QCheckBox('2a', parent), 
        QtGui.QCheckBox('2b', parent))

    for v in self.cbPair.values():
        for cb in v:
            cb.clicked.connect(self.updateCB)

def updateCB(self):
    cb = self.sender()
    is_checked = cb.isChecked()
    id = str(cb.text())
    try:
        # Update a whole column
        column = int(id[-1]) - 1
        rows = ('1', '2')
    except ValueError:
        # Update a row and the headers row
        rows = (id[0], )
        column = {'a': 1, 'b': 0}.get(id[-1])
        if not is_checked:
            for c in (0, 1):
                self.cbPair['0'][c].setChecked(is_checked)
    for r in rows:
        self.cbPair[r][column].setChecked(is_checked)

行と列の値が計算されるUIDとしてチェックボックスのテキストを使用していることに注意してください。チェックボックスに異なるテキスト ラベルを使用する場合は、UID をすべてのチェックボックスの属性として設定する必要がある場合があります。

于 2012-09-11T22:26:43.547 に答える