Python QCheckBox状态更改PyQt4

Python QCheckBox状态更改PyQt4,python,qt,pyqt,qcheckbox,Python,Qt,Pyqt,Qcheckbox,我正在尝试在PyQt4中实现一个系统,其中取消选中复选框将调用函数disable_mod,选中它将调用enable_mod。但是,即使状态正在更改,复选框也会调用它们开始使用的初始函数。在这种情况下,如果已经选中了一个复选框,它会一直调用disable_mod函数!我不明白为什么会这样?你们能帮我一点忙吗?这是我的密码: from PyQt4 import QtCore, QtGui from os import walk from os.path import join import sys

我正在尝试在PyQt4中实现一个系统,其中取消选中复选框将调用函数disable_mod,选中它将调用enable_mod。但是,即使状态正在更改,复选框也会调用它们开始使用的初始函数。在这种情况下,如果已经选中了一个复选框,它会一直调用disable_mod函数!我不明白为什么会这样?你们能帮我一点忙吗?这是我的密码:

from PyQt4 import QtCore, QtGui
from os import walk
from os.path import join
import sys

def list_files_regex(dir):
    l = []
    for (root, dirnames, filenames) in walk(dir):
        for d in dirnames:
            list_files_regex(join(root, d))
        l.extend(filenames)
    return l

directory = "J:/test_pack"
directory = join(directory, "/mods")

count = 0
for y in list_files_regex(directory):
    print y
    count += 1
print count

class ModEdit(QtGui.QMainWindow):
    def __init__(self, title, icon, x, y, w, h):
        super(ModEdit, self).__init__()
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(icon))
        self.setGeometry(x, y, w, h)
        self.choices = []
        self.init()

    def init(self):
        scroll_widget = QtGui.QScrollArea()
        sub_widget = QtGui.QWidget()
        v_layout = QtGui.QVBoxLayout()

        for y in list_files_regex(directory):
            tmp = QtGui.QCheckBox(y, self)
            tmp.resize(tmp.sizeHint())
            if tmp.text()[len(tmp.text()) - 8: len(tmp.text())] != 'disabled':
                tmp.setChecked(True)
            # if tmp.isChecked() == 0:
            #     tmp.stateChanged.connect(self.enable_mod)
            # if tmp.isChecked():
            #     tmp.stateChanged.connect(self.disable_mod)
            # v_layout.addWidget(tmp)
            self.choices.append(tmp)
        print self.choices
        for choice in self.choices:
            v_layout.addWidget(choice)
            if choice.isChecked():
                choice.stateChanged.connect(self.disable_mod)
            else:
                choice.stateChanged.connect(self.enable_mod)
        sub_widget.setLayout(v_layout)
        scroll_widget.setWidget(sub_widget)
        self.setCentralWidget(scroll_widget)
        self.show()

    def enable_mod(self):
        print "ENABLE_TEST"
        print self.choices[1].isChecked()
    def disable_mod(self):
        print "DISABLE_TEST"
        print self.choices[1].isChecked()

    def test(self):
        print 'test'
        for ch in self.choices:
            if ch.isChecked():
                ch.stateChanged.connect(self.disable_mod)
            else:
                ch.stateChanged.connect(self.enable_mod)

class Rename(QtCore.QObject):
    enable = QtCore.pyqtSignal
    disable = QtCore.pyqtSignal

app = QtGui.QApplication(sys.argv)
ex = ModEdit("Minecraft ModEdit", "ModEdit.png", 64, 64, 640, 480)
sys.exit(app.exec_())

问题在于,在初始化过程中,您只连接了一次复选框
stateChanged
信号。复选框的状态更改后,您不会断开信号并将其重新连接到正确的插槽

您需要将
stateChanged
信号连接到一个中间插槽,该插槽将根据复选框状态决定调用哪个函数。由于您将同一插槽用于多个复选框,因此最好也将复选框传递给该插槽

from functools import partial

def init(self):
    ...
    for tmp in list_of_checkboxes:
        enable_slot = partial(self.enable_mod, tmp)
        disable_slot = partial(self.disable_mod, tmp)
        tmp.stateChanged.connect(lambda x: enable_slot() if x else disable_slot())

def enable_mod(self, checkbox):
    print "ENABLE_TEST"
    print checkbox.isChecked()

def disable_mod(self, checkbox):
    print "DISABLE_TEST"
    print checkbox.isChecked()
或者,由于我们现在将复选框传递给插槽,您可以只使用一个插槽并检查插槽内的复选框状态

def init(self):
    ...
    for tmp in list_of_checkboxes:
        slot = partial(self.enable_disable_mod, tmp)
        tmp.stateChanged.connect(lambda x: slot())

def enable_disable_mod(self, checkbox):
    if checkbox.isChecked():
        ...
    else:
        ...

谢谢你解释这么多!你能告诉我lambda函数在这种特殊情况下的作用吗?我查过lambda函数,但在这个特殊情况下我感到困惑。第一种解决方案有效。第二个也有同样的问题@对于第二个解决方案,请注意,只有一个插槽同时处理检查和取消检查。对两个状态更改事件调用相同的函数;这是有意的。与基于检查状态调用不同的函数不同,您可以调用相同的函数,并通过测试函数内复选框的检查状态来拆分要运行的代码。