简体   繁体   English

QCheckBox状态改变PyQt4

[英]QCheckBox state change PyQt4

I'm trying to implement a system in PyQt4 where unchecking a checkbox would call function disable_mod and checking it would call enable_mod. 我正在尝试在PyQt4中实现一个系统,取消选中一个复选框会调用函数disable_mod并检查它会调用enable_mod。 But even though state is changing the checkboxes call the initial function they started with. 但即使状态正在改变复选框,也要调用它们开始的初始函数。 For this case if an already checked box was clicked it'd always keep calling the disable_mod function! 对于这种情况,如果单击已经选中的框,它将始终保持调用disable_mod函数! I don't understand why is this happening? 我不明白为什么会这样? Can you guys help me out here a little bit? 你们能帮帮我一点吗? Here's my code: 这是我的代码:

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_())

The problem is that you're only connecting the checkbox stateChanged signal once during initialization. 问题是,你只连接复选框stateChanged初始化过程中一次信号。 After the state of the checkbox changes, you're not disconnecting the signal and reconnecting it to the correct slot. 在复选框状态发生变化后,您不会断开信号并将其重新连接到正确的插槽。

You'll need to connect the stateChanged signal to an intermediary slot that will decide which function to call based on the checkbox state. 您需要将stateChanged信号连接到中间插槽,该插槽将根据复选框状态决定调用哪个函数。 Since you're using the same slot for multiple checkboxes, it's probably best to also pass the checkbox to the slot as well. 由于您在多个复选框中使用相同的插槽,因此最好也将复选框传递给插槽。

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()

Alternatively, since we are now passing the checkbox to the slots, you could just use a single slot and check the checkbox state inside the slot 或者,由于我们现在将复选框传递给插槽,您可以使用单个插槽并检查插槽内的复选框状态

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:
        ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM