PYQT5(20)-信号与槽-初级高级

信号(Signal)和槽(Slot)是Qt中的核心机制,也是在PyQt编程中对象之间进行通信的机制。在Qt中,每一个QObject对象和PyQt中所有继承自QWidget的控件(这些都是QObject的子对象)都支持信号与槽机制。当信号发射时,连接的槽函数将会自动执行。在PyQt5中信号与槽通过object.signal.connct()方法连接。

PyQt的窗口控件类中有很多内置信号,开发者也可以添加自定义信号。信号与槽具有如下特点:
一个信号可以连接多个槽。
一个信号可以连接另一个信号。
信号参数可以是任何Python类型。
一个槽可以监听多个信号。
信号与槽的连接方式可以是同步连接,也可以是异步连接。
信号与槽的连接可能会跨线程。
信号可能会断开。

在GUI编程中,当改变一个控件的状态时(如单击了按钮),通常需要通知另一个控件,也就是实现了对象之间的通信。在早期的GUI编程中使用的是回调机制,在Qt中则使用信号与槽。在编写一个类时,要先定义该类的信号与槽,在类中信号与槽进行连接,实现对象之间的数据传输。

当事件或者状态发生改变时,就会发出信号。同时,信号会触发所有与这个事件(信号)相关的函数(槽)。信号与槽可以是多对多的关系。一个信号可以连接多个槽,一个槽也可以监听多个信号。

PyQt的内置信号是自动定义的。使用PyQt5.QtCore.pyqtSignal()函数可以为QObject创建一个信号,使用pyqtSingnal()函数可以把信号定义为类的属性。使用connect()函数可以把信号绑定到槽函数上。使用disconnect()函数可以解除信号与槽函数的绑定。使用emit()函数可以发射信号。

信号与槽的入门应用

信号与槽有三种使用方法,第一种是内置信号与槽的使用,第二种是自定义信号与槽的使用, 第三种是装饰器的信号与槽的使用。

内置信号与槽的使用

代码示例

from PyQt5.QtWidgets import QPushButton, QApplication, QWidget
from PyQt5.QtWidgets import QMessageBox
import sys

app = QApplication(sys.argv)
widget = QWidget()


def showMsg():
    QMessageBox.information(widget, "信息提示框", "ok,弹出测试信息")


btn = QPushButton("测试点击按钮", widget)
btn.clicked.connect(showMsg)
widget.show()
sys.exit(app.exec_())

自定义信号与槽的使用 

自定义信号与槽的使用,是指在发射信号时,不使用窗口控件的函数,而是使用自定义的函数(简单地说,就是使用pyqtSignal类实例发射信号)。之所以要使用自定义信号与槽,是因为通过内置函数发射信号有自身的缺陷。首先,内置函数只包含一些常用的信号,有些信号的发射找不到对应的内置函数,其次,只有在特定情况下(如按钮的点击事件)才能发射这种信号;最后,内置函数传递的参数是特定的,不可以自定义。使用自定义的信号函数则没有这些缺陷。

在PyQt5编程中,自定义信号与槽的适用范围很灵活,比如因为业务需求,在程序中的某个地方需要发射一个信号,传递多种数据类型(实际上就是传递参数),然后在槽函数中接收传递过来的数据,这样就可以非常灵活地实现一些业务逻辑。

代码示例1

from PyQt5.QtCore import QObject, pyqtSignal


# 信号对象
class QTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(object)

    def __init__(self):
        super(QTypeSignal, self).__init__()

    def run(self):
        # 发射信号
        self.sendmsg.emit('Hello Pyqt5')


# 槽对象          
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

        # 槽对象里的槽函数

    def get(self, msg):
        print("QSlot get msg => " + msg)


if __name__ == '__main__':
    send = QTypeSignal()
    slot = QTypeSlot()
    # 生成一个信号
    print('--- 把信号绑定到槽函数 ---')
    send.sendmsg.connect(slot.get)
    send.run()

    print('--- 把信号断开槽函数 ---')
    send.sendmsg.disconnect(slot.get)
    send.run()

代码示例2

from PyQt5.QtCore import QObject, pyqtSignal


# 信号对象
class QTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(str, str)

    def __init__(self):
        super(QTypeSignal, self).__init__()

    def run(self):
        # 发射信号
        self.sendmsg.emit('第一个参数', '第二个参数')


# 槽对象          
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

    # 槽对象里的槽函数      
    def get(self, msg1, msg2):
        print("QSlot get msg => " + msg1 + ' ' + msg2)


if __name__ == '__main__':
    send = QTypeSignal()
    slot = QTypeSlot()
    # 1
    print('--- 把信号绑定到槽函数 ---')
    send.sendmsg.connect(slot.get)
    send.run()

    # 2
    print('--- 把信号断开槽函数 ---')
    send.sendmsg.disconnect(slot.get)
    send.run()

信号与槽再细分

内置信号和槽函数

代码示例

from PyQt5.QtWidgets import *
import sys


class Winform(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('内置的信号/槽示例')
        self.resize(330, 50)
        btn = QPushButton('关闭', self)
        btn.clicked.connect(self.close)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Winform()
    win.show()
    sys.exit(app.exec_())

内置信号和自定义槽函数

代码示例

from PyQt5.QtWidgets import *
import sys


class Winform(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('内置的信号和自定义槽函数示例')
        self.resize(330, 50)
        btn = QPushButton('关闭', self)
        btn.clicked.connect(self.btn_close)

    def btn_close(self):
        # 自定义槽函数
        self.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Winform()
    win.show()
    sys.exit(app.exec_())

自定义信号和内置槽函数

代码示例

from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSignal
import sys


class Winform(QWidget):
    # 自定义信号,不带参数
    button_clicked_signal = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('自定义信号和内置槽函数示例')
        self.resize(330, 50)
        btn = QPushButton('关闭', self)
        # 连接 信号和槽
        btn.clicked.connect(self.btn_clicked)
        # 接收信号,连接到槽
        self.button_clicked_signal.connect(self.close)

    def btn_clicked(self):
        # 发送自定义信号,无参数
        self.button_clicked_signal.emit()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Winform()
    win.show()
    sys.exit(app.exec_())

自定义信号和槽函数

代码示例

from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSignal
import sys


class Winform(QWidget):
    # 自定义信号,不带参数
    button_clicked_signal = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('自定义信号和槽函数示例')
        self.resize(330, 50)
        btn = QPushButton('关闭', self)
        # 连接 信号和槽
        btn.clicked.connect(self.btn_clicked)
        # 接收信号,连接到自定义槽函数
        self.button_clicked_signal.connect(self.btn_close)

    def btn_clicked(self):
        # 发送自定义信号,无参数
        self.button_clicked_signal.emit()

    def btn_close(self):
        self.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Winform()
    win.show()
    sys.exit(app.exec_())

高级用法

高级自定义信号和槽

一般流程:

(1)定义信号。
(2)定义槽函数。
(3)连接信号与槽函数。
(4)发射信号。

代码示例

from PyQt5.QtCore import QObject, pyqtSignal


class CustSignal(QObject):
    """
    1、定义信号
    """
    # 声明一个无参数的信号
    signal1 = pyqtSignal()

    # 声明带一个int类型参数的信号
    signal2 = pyqtSignal(int)

    # 声明带一个int和str类型参数的信号
    signal3 = pyqtSignal(int, str)

    # 声明带一个列表类型参数的信号
    signal4 = pyqtSignal(list)

    # 声明带一个字典类型参数的信号
    signal5 = pyqtSignal(dict)

    # 声明一个多重载版本的信号,包括了一个带int和str类型参数的信号或着带str参数的信号
    signal6 = pyqtSignal([int, str], [str])

    def __init__(self, parent=None):
        super(CustSignal, self).__init__(parent)
        """
        3、信号连接到指定槽
        """
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall3)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[int, str].connect(self.signalCall6)
        self.signal6[str].connect(self.signalCall6OverLoad)
        """
        4、信号发射
        """
        self.signal1.emit()
        self.signal2.emit(1)
        self.signal3.emit(1, "text")
        self.signal4.emit([1, 2, 3, 4])
        self.signal5.emit({"name": "wangwu", "age": "25"})
        self.signal6[int, str].emit(1, "text")
        self.signal6[str].emit("text")

    """
    2、定义槽函数
    """
    def signalCall1(self):
        print("signal1 emit")

    def signalCall2(self, val):
        print("signal2 emit,value:", val)

    def signalCall3(self, val, text):
        print("signal3 emit,value:", val, text)

    def signalCall4(self, val):
        print("signal4 emit,value:", val)

    def signalCall5(self, val):
        print("signal5 emit,value:", val)

    def signalCall6(self, val, text):
        print("signal6 emit,value:", val, text)

    def signalCall6OverLoad(self, val):
        print("signal6 overload emit,value:", val)


if __name__ == '__main__':
    custSignal = CustSignal()

使用自定义参数

信号发出的参数个数为0,槽函数接收的参数个数为1,由于0<1,这样运行起来一定会报错(原因是信号发出的参数个数一定要大于槽函数接收的参数个数。解决这个问题通过自定义参数的传递。

代码示例1:使用lambda表达式

from PyQt5.QtWidgets import QMainWindow, QPushButton, QWidget, QMessageBox, QApplication, QHBoxLayout
import sys


class WinForm(QMainWindow):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("信号和槽传递额外参数例子")
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')

        button1.clicked.connect(lambda: self.onButtonClick(1))
        button2.clicked.connect(lambda: self.onButtonClick(2))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)
        self.setCentralWidget(main_frame)

    def onButtonClick(self, n):
        print('Button {0} 被按下了'.format(n))
        QMessageBox.information(self, "信息提示框", 'Button {0} clicked'.format(n))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec_())

 代码示例2:使用functools中的partial函数

from PyQt5.QtWidgets import QMainWindow, QPushButton, QWidget, QMessageBox, QApplication, QHBoxLayout
import sys
from functools import partial


class WinForm(QMainWindow):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("信号和槽传递额外参数例子")
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')

        button1.clicked.connect(partial(self.onButtonClick, 1))
        button2.clicked.connect(partial(self.onButtonClick, 2))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)
        self.setCentralWidget(main_frame)

    def onButtonClick(self, n):
        print('Button {0} 被按下了'.format(n))
        QMessageBox.information(self, "信息提示框", 'Button {0} clicked'.format(n))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec_())

装饰器信号与槽

代码示例

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton
import sys


class CustWidget(QWidget):

    def __init__(self, parent=None):
        super(CustWidget, self).__init__(parent)

        self.okButton = QPushButton("OK", self)
        # 使用setObjectName设置对象名称
        self.okButton.setObjectName("okButton")
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        self.setLayout(layout)
        # PyQt5中根据信号名称自动连接到槽函数的核心代码。
        # 这行代码用来将QObject中的子孙对象的某些信号按照其objectName连接到相应的槽函数。
        QtCore.QMetaObject.connectSlotsByName(self)

    @QtCore.pyqtSlot()
    def on_okButton_clicked(self):
        print("点击了OK按钮")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = CustWidget()
    win.show()
    sys.exit(app.exec_())

代码示例等价转换

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton
import sys


class CustWidget(QWidget):

    def __init__(self, parent=None):
        super(CustWidget, self).__init__(parent)

        self.okButton = QPushButton("OK", self)
        # 使用setObjectName设置对象名称
        self.okButton.setObjectName("okButton")
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        self.setLayout(layout)
        # 等价转换
        QtCore.QMetaObject.connectSlotsByName(self)
        self.okButton.clicked.connect(self.okButton_clicked)

    def okButton_clicked(self):
        print("点击了OK按钮")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = CustWidget()
    win.show()
    sys.exit(app.exec_())

信号与槽的断开和连接

代码示例

from PyQt5.QtCore import QObject, pyqtSignal


class SignalClass(QObject):
    # 声明一个无参数的信号
    signal1 = pyqtSignal()

    # 声明带一个int类型参数的信号
    signal2 = pyqtSignal(int)

    def __init__(self, parent=None):
        super(SignalClass, self).__init__(parent)

        # 信号sin1连接到sin1Call和sin2Call这两个槽
        self.signal1.connect(self.sin1Call)
        self.signal1.connect(self.sin2Call)

        # 信号sin2连接到信号sin1
        self.signal2.connect(self.signal1)

        # 信号发射
        self.signal1.emit()
        self.signal2.emit(1)

        # 断开sin1、sin2信号与各槽的连接
        self.signal1.disconnect(self.sin1Call)
        self.signal1.disconnect(self.sin2Call)
        self.signal2.disconnect(self.signal1)

        # 信号sin1和sin2连接同一个槽sin1Call
        self.signal1.connect(self.sin1Call)
        self.signal2.connect(self.sin1Call)

        # 信号再次发射
        self.signal1.emit()
        self.signal2.emit(1)

    def sin1Call(self):
        print("signal-1 emit")

    def sin2Call(self):
        print("signal-2 emit")


if __name__ == '__main__':
    signal = SignalClass()

 Qt Designer协助:界面显示与业务逻辑的分离

代码示例

本例要实现的功能是:通过一个模拟打印的界面来详细说明信号的使用,在打印时可以设置打印的份数、纸张类型,触发“打印”按钮后,将执行结果显示在右侧通过QCheckBox(“全屏预览”复选框)来选择是否通过全屏模式进行预览,将执行结果显示在右侧。
按F1键,可以显示helpMessage信息。

 窗口控件说明

控件类型控件名称作 用
QSpinBoxnumberSpinBox显示打印的份数
QComboBoxstyleCombo显示打印的纸张类型。纸张类型包括A3、A4和A5纸
QPushButtonprintButton连接emitPrintSignal函数的绑定。触发自定义信号printSignal的发射
QCheckBoxpreviewStatus是否全屏预览
QPushButtonpreviewButton连接cmitPreviewSignal函数的绑定。触发自定义信号previewSignal的发射
QLabelresultLabel显示执行结果

转py文件

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(715, 225)
        self.controlsGroup = QtWidgets.QGroupBox(Form)
        self.controlsGroup.setGeometry(QtCore.QRect(10, 20, 451, 151))
        self.controlsGroup.setObjectName("controlsGroup")
        self.widget = QtWidgets.QWidget(self.controlsGroup)
        self.widget.setGeometry(QtCore.QRect(10, 40, 411, 30))
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.numberSpinBox = QtWidgets.QSpinBox(self.widget)
        self.numberSpinBox.setObjectName("numberSpinBox")
        self.horizontalLayout.addWidget(self.numberSpinBox)
        self.styleCombo = QtWidgets.QComboBox(self.widget)
        self.styleCombo.setObjectName("styleCombo")
        self.styleCombo.addItem("")
        self.styleCombo.addItem("")
        self.styleCombo.addItem("")
        self.horizontalLayout.addWidget(self.styleCombo)
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.printButton = QtWidgets.QPushButton(self.widget)
        self.printButton.setObjectName("printButton")
        self.horizontalLayout.addWidget(self.printButton)
        self.widget1 = QtWidgets.QWidget(self.controlsGroup)
        self.widget1.setGeometry(QtCore.QRect(10, 100, 201, 30))
        self.widget1.setObjectName("widget1")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.previewStatus = QtWidgets.QCheckBox(self.widget1)
        self.previewStatus.setObjectName("previewStatus")
        self.horizontalLayout_2.addWidget(self.previewStatus)
        self.previewButton = QtWidgets.QPushButton(self.widget1)
        self.previewButton.setObjectName("previewButton")
        self.horizontalLayout_2.addWidget(self.previewButton)
        self.resultGroup = QtWidgets.QGroupBox(Form)
        self.resultGroup.setGeometry(QtCore.QRect(470, 20, 231, 151))
        self.resultGroup.setObjectName("resultGroup")
        self.resultLabel = QtWidgets.QLabel(self.resultGroup)
        self.resultLabel.setGeometry(QtCore.QRect(20, 30, 191, 101))
        self.resultLabel.setObjectName("resultLabel")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "打印控件"))
        self.controlsGroup.setTitle(_translate("Form", "打印控制"))
        self.label.setText(_translate("Form", "打印份数:"))
        self.styleCombo.setItemText(0, _translate("Form", "A3"))
        self.styleCombo.setItemText(1, _translate("Form", "A4"))
        self.styleCombo.setItemText(2, _translate("Form", "A5"))
        self.label_2.setText(_translate("Form", "纸张类型:"))
        self.printButton.setText(_translate("Form", "打印"))
        self.previewStatus.setText(_translate("Form", "全屏预览"))
        self.previewButton.setText(_translate("Form", "预览"))
        self.resultGroup.setTitle(_translate("Form", "操作结果"))
        self.resultLabel.setText(_translate("Form", "<html><head/><body><p><br/></p></body></html>"))

为了使窗口的显示和业务逻辑分离,再新建一个调用窗口显示的文件CallMainWinSignalSlog02.py,在调用类中添加多个自定义信号,并与槽函数进行绑定。

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from MainWinSignalSlog02 import Ui_Form
from PyQt5.QtCore import pyqtSignal, Qt


class MyMainWindow(QMainWindow, Ui_Form):
    helpSignal = pyqtSignal(str)
    printSignal = pyqtSignal(list)
    # 声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
    previewSignal = pyqtSignal([int, str], [str])

    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.initUI()

    def initUI(self):
        self.helpSignal.connect(self.showHelpMessage)
        self.printSignal.connect(self.printPaper)
        self.previewSignal[str].connect(self.previewPaper)
        self.previewSignal[int, str].connect(self.previewPaperWithArgs)

        self.printButton.clicked.connect(self.emitPrintSignal)
        self.previewButton.clicked.connect(self.emitPreviewSignal)

    # 发射预览信号
    def emitPreviewSignal(self):
        if self.previewStatus.isChecked() == True:
            self.previewSignal[int, str].emit(1080, " Full Screen")
        elif self.previewStatus.isChecked() == False:
            self.previewSignal[str].emit("Preview")

    # 发射打印信号
    def emitPrintSignal(self):
        pList = []
        pList.append(self.numberSpinBox.value())
        pList.append(self.styleCombo.currentText())
        self.printSignal.emit(pList)

    def printPaper(self, list):
        self.resultLabel.setText("打印: " + "份数:" + str(list[0]) + " 纸张:" + str(list[1]))

    def previewPaperWithArgs(self, style, text):
        self.resultLabel.setText(str(style) + text)

    def previewPaper(self, text):
        self.resultLabel.setText(text)

    # 重载点击键盘事件
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_F1:
            self.helpSignal.emit("help message")

    # 显示帮助消息
    def showHelpMessage(self, message):
        self.resultLabel.setText(message)
        self.statusBar().showMessage(message)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MyMainWindow()
    win.show()
    sys.exit(app.exec_())

(1)自定义信号在init()函数之前定义。
(2)自定义信号可以传递如str、int、list、object、float、tuple、dict等很多类型的参数。
(3)注意signal和slot的调用逻辑,避免signal和slot之间出现死循环,比如在slot方法中继续发射该信号。

多线程中信号与槽的使用

代码示例1

from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import QThread, pyqtSignal
import sys


class Main(QWidget):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)

        # 创建一个线程实例并设置名称、变量、信号槽
        self.thread = MyThread()
        self.thread.setIdentity("thread1")
        self.thread.sinOut.connect(self.outText)
        self.thread.setVal(6)

    def outText(self, text):
        print(text)


class MyThread(QThread):
    sinOut = pyqtSignal(str)

    def __init__(self, parent=None):
        super(MyThread, self).__init__(parent)
        self.identity = None

    def setIdentity(self, text):
        self.identity = text

    def setVal(self, val):
        self.times = int(val)
        # 执行线程的run方法
        self.start()

    def run(self):
        while self.times > 0 and self.identity:
            # 发射信号
            self.sinOut.emit(self.identity + "==>" + str(self.times))
            self.times -= 1


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

代码示例2

本例中,定义了一个后台线程类BackendThread来模拟后台耗时操作,在这个线程类中定义了信号update_date。使用BackendThread线程类在后台处理数据,每秒发射一次自定义信号update_date。

在初始化窗口界面时,定义后台线程类BackendThread,并把线程类的信号update_date连接到槽函数handleDisplay()。这样后台线程每发射一次信号,就可以把最新的时间值实时显示在前台窗口的QLineEdit文本对话框中。

from PyQt5.QtCore import QThread, pyqtSignal, QDateTime
from PyQt5.QtWidgets import QApplication, QDialog, QLineEdit
import time
import sys


class BackendThread(QThread):
    # 通过类成员对象定义信号对象  
    update_date = pyqtSignal(str)

    # 处理要做的业务逻辑
    def run(self):
        while True:
            data = QDateTime.currentDateTime()
            currTime = data.toString("yyyy-MM-dd hh:mm:ss")
            self.update_date.emit(str(currTime))
            time.sleep(1)


class Window(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.setWindowTitle('pyqt5界面实时更新例子')
        self.resize(400, 100)
        self.input = QLineEdit(self)
        self.input.resize(400, 100)
        self.initUI()

    def initUI(self):
        # 创建线程  
        self.backend = BackendThread()
        # 连接信号 
        self.backend.update_date.connect(self.handleDisplay)
        # 开始线程  
        self.backend.start()

    # 将当前时间输出到文本框
    def handleDisplay(self, data):
        self.input.setText(data)


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

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AdolphW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值