自定义类中的信号和插槽,包括PyQt QWidget不起作用

问题描述 投票:0回答:1

我在定制包含QPushButtonQLabel的类时遇到了麻烦,我只想设置QPushButton可检查的对象,并为其触发信号定义一个插槽,此外,还有定制类固有的QObject

下面显示代码,

import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import pyqtSlot, QObject


class CustomButton(QPushButton):
    def __init__(self, label='', parent=None):
        super().__init__(label, parent)
        self.setCheckable(True)
        self.toggled.connect(self.update)

    def update(self, state):
        if state:
            self.setStyleSheet('background-color: green')
        else:
            self.setStyleSheet('background-color: red')

class ButtonCtrl(QObject):
    def __init__(self,  parent=None, label=''):
        super().__init__()
        if isinstance(parent, QLayout):
            col = QVBoxLayout()
            parent.addLayout(col)
        else:
            col = QVBoxLayout(parent)
        self.text = ['ON', 'OFF']
        self.label = QLabel(label)
        self.button = QPushButton('ON')
        # self.button = CustomButton('ON')
        col.addWidget(self.label)
        col.addWidget(self.button)
        self.button.setCheckable(True)
        self.button.setChecked(True)
        self.button.toggled.connect(self.update)
        self.update(True)
        self.label.setFont(QFont('Microsoft YaHei', 14))
        self.button.setFont(QFont('Microsoft YaHei', 12, True))
        self.button.toggle()

    # @pyqtSlot(bool)
    def update(self, state):
        if state:
            self.button.setText(self.text[0])
            self.button.setStyleSheet('background-color: green')
        else:
            self.button.setText(self.text[-1])
            self.button.setStyleSheet('background-color: red')


class Window(QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        # set the layout
        layout = QVBoxLayout(self)
        but = ButtonCtrl(layout, "Test")
        #self.but = ButtonCtrl(layout, "Test")
        btn = CustomButton()
        layout.addWidget(btn)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    main = Window()
    main.show()
    sys.exit(app.exec_())

我自定义了两个按钮,分别命名为CustomButton(QPushButton)ButtonCtrl(QObject),并且已经在主窗口中测试了插槽,但是后台更新插槽对CustomButton(QPushbutton)有效,而对ButtonCtrl(QObject)无效,插槽功能甚至没有被调用。

但是,如果我将ButtonCtrl(QObject)的按钮成员从QPushButton更改为我的CustomButton(QPushButton),它将在主窗口中很好地工作。此外,如果通过设置but,主窗口中的self.but=ButtonCtrl(layout, "Test")成为主窗口类的成员,它也将起作用。

我在Qt文档中没有找到直接答案,这说明了这一点

当对象的内部状态以某种可能使对象的客户端或所有者感兴趣的方式更改时,该对象发出信号。信号是公共访问函数,可以从任何地方发出,但是我们建议仅从定义信号及其子类的类中发出信号。

我不确定but的寿命是否会引起这种影响,希望得到答案,谢谢。

python pyqt pyqt5
1个回答
0
投票

问题很简单:ButtonCtrl类对象具有局部作用域,因此将被销毁,为什么CustomButton类对象不会发生同样的事情?好吧,因为QWidget的所有权有其父级,而该按钮的父级是窗口,所以ButtonCtrl对象没有它。在这种情况下,解决方案是延长变量的生命周期,对于QObject,有几种选择:

  • 使类成员变量,
  • 将其放入使用寿命更长的容器中,或
  • 建立具有更长生命周期的QObject父对象。

使用第三个替代方法只是更改为:

class ButtonCtrl(QObject):
    def __init__(self,  parent=None, label=''):
        super().__init__(parent)
        # ...
© www.soinside.com 2019 - 2024. All rights reserved.