我在定制包含QPushButton
和QLabel
的类时遇到了麻烦,我只想设置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
的寿命是否会引起这种影响,希望得到答案,谢谢。
问题很简单:ButtonCtrl类对象具有局部作用域,因此将被销毁,为什么CustomButton类对象不会发生同样的事情?好吧,因为QWidget的所有权有其父级,而该按钮的父级是窗口,所以ButtonCtrl对象没有它。在这种情况下,解决方案是延长变量的生命周期,对于QObject,有几种选择:
使用第三个替代方法只是更改为:
class ButtonCtrl(QObject):
def __init__(self, parent=None, label=''):
super().__init__(parent)
# ...