PyQt 4 - 如何在特定的模块化生成的小部件之间建立信号

时间:2012-09-06 00:54:44

标签: python pyqt4

所以我有2个QCheckBoxes列表来驱动彼此的状态变化。每个列表都位于一个选项卡中,该选项卡属于一组选项卡,属于主选项卡。当我生成复选框时,我一次生成一个选项卡,每个选项卡都有一个唯一的名称。我想知道我是否可以查看列表1中的特定复选框,并在列表2中有一个特定复选框的状态更改?

实施例。结构

mainTab1 > tab 1 > list 1 checkBox 1-9
         > tab 2 > list 1 checkBox 1-4
         > tab 3 > list 1 checkBox 1-6

mainTab2 > tab 1 > list 2 checkBox 1-3
         > tab 2 > list 2 checkBox 1-11
         > tab 3 > list 2 checkBox 1-8

使用这种结构,如果我检查mainTab1> tab2> list1checkBox3,我希望mainTab2> tab1> list2checkBox1检查该更改,我应该如何连接我的信号?

这是实际生成标签和复选框的代码

    global clusterNames
    global parseByPass
    totalPasses = parseByPass.keys()
    totalPasses.sort()
    cNames = reversed(clusterNames)
    assetCBList, assetNameList, assetPassList, assetROList = [],[],[],[]
    passCBList, passNameList, passPassList, passROList = [],[],[],[]        

    #Create the main window
    self.setFixedSize(900,600)
    self.setWindowTitle("Que Dispatcher")

    #Create all the layouts to be used by main window
    self.windowLayout = QtGui.QVBoxLayout()
    self.buttonShelf = QtGui.QHBoxLayout()

    #Create the tab widget
    self.tabGroupMain = QtGui.QTabWidget(self)
    self.tabGroupMain.setObjectName("tabGroupMain")
    self.tabGroupMain.setGeometry(QtCore.QRect(10,10,875,530))
    self.tabGroupSub = QtGui.QTabWidget(self)
    self.tabGroupSub.setObjectName("tabGroupSub")
    self.tabGroupSub.setGeometry(QtCore.QRect(10,10,865,520))
    self.tabGroupSub.setStyleSheet("border: 0px")
    self.tabGroupSub2 = QtGui.QTabWidget(self)
    self.tabGroupSub2.setObjectName("tabGroupSub2")
    self.tabGroupSub2.setGeometry(QtCore.QRect(10,10,865,520))
    self.tabGroupSub2.setStyleSheet("border: 0px")

    #Create all the tabs and add them to the tab widget
    #Asset tab      
    for index, item in enumerate(cNames):
        currentTab = item + "Tab"
        self.currentTab = QtGui.QWidget()
        self.currentTab.setObjectName(currentTab)

        #Create the top line, all control widgets
        self.tabV = QtGui.QVBoxLayout()
        self.tabScroll = QtGui.QScrollArea()
        self.tabLayout = QtGui.QGridLayout()
        self.tabLayout.setColumnMinimumWidth(1,175)
        self.tabLayout.setColumnMinimumWidth(2,125)
        self.tabLayout.setRowMinimumHeight(1,15)
        self.allCB = QtGui.QCheckBox()
        self.allCB.setObjectName("%sAllCB" % item)
        self.allNameLabel = QtGui.QLabel("Cluster Name")
        self.allNameLabel.setObjectName("%sAllNameLable" % item)
        self.allPassLabel = QtGui.QLabel("Pass Type")
        self.allPassLabel.setObjectName("%sAllPassLabel" % item)
        self.allRenderOpt = QtGui.QLineEdit("Render Options: Insert Commands")
        self.allRenderOpt.setObjectName("%sAllRenderOpt" % item)

        #Create modullar widgets based on parsed info
        for index, stat in enumerate(QParsed[item][1]):
            statedRO = ""
            assetCB = item  + stat + "CheckBox"
            assetNameLabel = item + stat + "NameLabel"
            assetPassLabel = item + stat + "PassLabel"
            assetRO = item + stat + "ROTF"
            for text in QParsed[item][2][index]:
                statedRO = statedRO + text + " "

            #Add modularly generated widgets with parsed info
            self.assetCB = QtGui.QCheckBox()
            self.assetCB.setObjectName(assetCB)
            self.assetNameLabel = QtGui.QLabel(item)
            self.assetNameLabel.setObjectName(assetNameLabel)
            self.assetPassLabel = QtGui.QLabel(stat)
            self.assetPassLabel.setObjectName(assetPassLabel)
            self.assetRenderOpt = QtGui.QLineEdit(statedRO)
            self.assetRenderOpt.setObjectName(assetRO)

            #Add the all control widgets to a horizontal layout
            self.tabLayout.addWidget(self.allCB,0,0)
            self.tabLayout.addWidget(self.allNameLabel,0,1)
            self.tabLayout.addWidget(self.allPassLabel,0,2)
            self.tabLayout.addWidget(self.allRenderOpt,0,3)

            #Add all modullar widgets
            self.tabLayout.addWidget(self.assetCB, (index+2), 0, QtCore.Qt.AlignTop)
            self.tabLayout.addWidget(self.assetNameLabel, (index +2), 1, QtCore.Qt.AlignTop)
            self.tabLayout.addWidget(self.assetPassLabel, (index +2), 2, QtCore.Qt.AlignTop)    
            self.tabLayout.addWidget(self.assetRenderOpt, (index +2), 3, QtCore.Qt.AlignTop)

        #Add layout to page of current tab widget
        self.tabV.addLayout(self.tabLayout)
        self.tabScroll.setLayout(self.tabV)
        self.tabScroll.setMinimumHeight(850)
        self.tabV.addStretch()
        self.tabGroupSub.addTab(self.tabScroll, item)

1 个答案:

答案 0 :(得分:0)

同步两个复选框非常简单。您将stateChanged信号从一个信号连接到另一个信号的setCheckState信号,反之亦然:

 checkbox1.stateChanged.connect(checkbox2.setCheckState)
 checkbox2.stateChanged.connect(checkbox1.setCheckState)

现在您只需要在合适的容器中整理复选框,然后根据需要连接信号。由于您拥有唯一的objectName,因此对于密钥和相应的dict实例,objectName QCheckBox的值似乎已经足够了。然后你可以有一个同步对列表。环绕它们并连接信号。

如果我正确理解你的代码,这应该是它的样子(用不相关的位剪断以强调逻辑):

# some code snipped here
# ...
self.checkBoxes = {}
# this is just an example
# your real syncPairs should include real names and full list of pairs of course
self.syncPairs = [('list2checkBox1', 'list1checkBox3')] 

for index, item in enumerate(cNames):
    # more code snipped here

    self.allCB = QtGui.QCheckBox()   # I'm not sure about 'self.' part
                                        # You are discarding the old one in the next iteration
                                        # So this will just store the last one in the iteration
                                        # Besides we are going to keep references to all in `self.checkBoxes`
    self.allCB.setObjectName("%sAllCB" % item)

    # here add it to the dict
    self.checkBoxes["%sAllCB" % item] = self.allCB

    # code snipped here

    # btw, you should add these ones to the layout _here_, not in the inner loop. So:
    self.tabLayout.addWidget(self.allCB,0,0)
    self.tabLayout.addWidget(self.allNameLabel,0,1)
    self.tabLayout.addWidget(self.allPassLabel,0,2)
    self.tabLayout.addWidget(self.allRenderOpt,0,3)

    #Create modullar widgets based on parsed info
    for index, stat in enumerate(QParsed[item][1]):
        # code snipped here

        #Add modularly generated widgets with parsed info
        self.assetCB = QtGui.QCheckBox()      # Again, same issue with 'self.'
        self.assetCB.setObjectName(assetCB)

        # add it to the dict
        self.checkBoxes[assetCB] = self.assetCB

        # rest of the code snipped

# after the setup done, we can connect the signals that will keep sync status:
for cb1, cb2 in self.syncPairs:
     self.checkBoxes[cb1].stateChanged.connect(self.checkBoxes[cb2].setCheckState)
     self.checkBoxes[cb2].stateChanged.connect(self.checkBoxes[cb1].setCheckState)

修改

两个同步复选框的简单演示:

import sys
from PyQt4 import QtGui

class Dialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)

        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)

        self.cb1 = QtGui.QCheckBox('checkbox 1')
        self.cb2 = QtGui.QCheckBox('checkbox 2')

        #self.cb1.stateChanged.connect(self.cb2.setCheckState)
        #self.cb2.stateChanged.connect(self.cb1.setCheckState)

        # alternatively
        self.cb1.toggled.connect(self.cb2.setChecked)
        self.cb2.toggled.connect(self.cb1.setChecked)

        layout.addWidget(self.cb1)
        layout.addWidget(self.cb2)

        self.setWindowTitle('Synced checkboxes')


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    main = Dialog()
    main.show()

    sys.exit(app.exec_())