簡體   English   中英

自定義 class 中的信號和插槽,包括 PyQt QWidget 不工作

[英]The signal and slot within custom class including PyQt QWidget not working

我在自定義包含QPushButtonQLabel的 class 時遇到了一些麻煩,我只想將QPushButton設置為可檢查並為其切換信號定義一個插槽,此外,自定義 class 固有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) ,並且我已經測試了主 window 中的插槽,但是后台更新插槽適用於CustomButton(QPushbutton)而不適用於ButtonCtrl(QObject) ,槽 function 甚至沒有被調用。

但是,如果我將ButtonCtrl(QObject)的按鈕成員從QPushButton更改為我的CustomButton(QPushButton) ,它將在主 window 中正常工作。 此外,如果主 window 中的but通過設置self.but=ButtonCtrl(layout, "Test")成為主 window class 的成員,它也可以正常工作。

我在 Qt 文檔中沒有找到直接答案,該文檔解釋了這一點

當 state 的內部 state 以某種可能對對象的客戶或所有者感興趣的方式發生變化時,信號由 object 發出。 信號是公共訪問函數,可以從任何地方發出,但我們建議僅從定義信號及其子類的 class 發出它們。

我不確定是否會導致這種影響的壽命but希望得到答復,謝謝。

The problem is simple: The ButtonCtrl class object has a local scope so it will be destroyed, and why doesn't the same happen with the CustomButton class object? 好吧,因為 QWidget 的所有權有其父級,並且該按鈕的父級是 window,而不是 ButtonCtrl object 沒有它。 在這種情況下,解決方案是延長變量的生命周期,在 QObject 的情況下有幾個選項:

  • 使 class 成員變量,
  • 將其放入生命周期較長的容器中,或
  • 建立一個生命周期更長的 QObject 父級。

使用第三種選擇只是更改為:

class ButtonCtrl(QObject):
    def __init__(self,  parent=None, label=''):
        super().__init__(parent)
        # ...

第一個選項是您的代碼中注釋的選項:

self.but = ButtonCtrl(layout, "Test")

第二個類似:

self.container = list()
but = ButtonCtrl(layout, "Test")
self.container.append(but)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM