pyqt5 弹窗,弹出自定义窗口。在线程中打开弹窗,不会卡死的方法。

1.需求分析

在用pyqt5做UI项目时,有需要用到弹出自定义窗口的需求,这里就研究了一下。效果如图:
在这里插入图片描述
这个本身是比较简单的一个操作,点击按钮然后让自定义的窗口显示。如果只是点击弹出自定义窗体是很简单的,但是如果需要在一个线程里面弹出一个窗体,就不是简单的调用显示就行可以了的。下面我是2种方法的实现

2.简单的单击显示窗体

这里的思路是,先实例化一个主窗体A,然后再实例化一个窗体B,然后再主窗体A中show这个窗体B。
代码如下:


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'treewidget.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtCore, QtGui, QtWidgets

#主窗体
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(447, 403)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(100, 170, 231, 61))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(18)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(120, 60, 191, 61))
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(26)
        self.label.setFont(font)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 447, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "线程中打开widget"))
        self.label.setText(_translate("MainWindow", "我是主窗体"))

#弹出窗体
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 234)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(120, 50, 251, 81))
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(26)
        self.label.setFont(font)
        self.label.setObjectName("label")

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "我是弹窗"))


class Main_Test(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Main_Test, self).__init__(parent)
        self.setupUi(self)
        # 在主窗体中实例弹出窗体
        self.wd = Widget_Test()
        # 链接槽函数
        self.pushButton.clicked.connect(self.pushbuttonfunc)
    # 显示弹出窗体
    def pushbuttonfunc(self):
        self.wd.showwidget()

# 弹出窗体类
class Widget_Test(QtWidgets.QWidget, Ui_Form):

    def __init__(self):
        super(Widget_Test, self).__init__()
        self.setupUi(self)

    def showwidget(self):
        self.show()


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

3.在线程中显示弹出窗体,不会卡死

如果在线程中,也如上面的方式弹出窗体,会造成主窗体卡死,因为不在同一个线程,操作需要用信号与槽的方式来实现显示窗体。在线程中发一个信号给主窗体,这样就不会造成主窗体卡死的现象了。具体的实现如下。
代码如下:


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'treewidget.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5 import QtCore, QtGui, QtWidgets
import threading
import queue

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(447, 403)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(100, 170, 231, 61))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(18)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(120, 60, 191, 61))
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(26)
        self.label.setFont(font)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 447, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "线程中打开widget"))
        self.label.setText(_translate("MainWindow", "我是主窗体"))


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 234)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(120, 50, 251, 81))
        font = QtGui.QFont()
        font.setFamily("仿宋")
        font.setPointSize(26)
        self.label.setFont(font)
        self.label.setObjectName("label")

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "我是弹窗"))


class Main_Test(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Main_Test, self).__init__(parent)
        self.setupUi(self)
        # 实例一个窗体
        self.wd = Widget_Test()
        # 链接槽函数
        self.pushButton.clicked.connect(self.pushbuttonfunc)
        # 为显示子窗口的信号增加槽函数
        self.wd.signal.connect(self.widget_show)

    def pushbuttonfunc(self):
        # 往队列中灌入一个信号
        self.wd.widget_queue.put("show")

    # 显示子窗口
    def widget_show(self):
        self.wd.show()


class Widget_Test(QtWidgets.QWidget, Ui_Form):
    signal = pyqtSignal()

    def __init__(self):
        super(Widget_Test, self).__init__()
        self.setupUi(self)
        # 申请一个消息队列
        self.widget_queue = queue.Queue(maxsize=-1)
        # 初始化一个线程
        self.widget_thread = threading.Thread(target=self.widget_handle)
        # 打开线程
        self.widget_thread.start()

    def send_single(self):
        # 发送信号到主窗体
        self.signal.emit()

    def widget_handle(self):
        while 1:
            # 在队列中获取一个信号
            strinfo = self.widget_queue.get(1)
            print(strinfo)
            if strinfo == "show":
                # 线程中弹出窗体,需要用到信号
                self.send_single()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Main_Test()
    win.show()
    sys.exit(app.exec_())
  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值