Pyqt5使用多线程解决界面卡顿并将命令行输出重定向到UI

先使用qtdesigner画两个按钮和两个text,用来检测功能。

在使用pyuic将其转换为py文件。

先给按钮2定义一个简单的函数,运行。

import thread_update
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import *
import sys, os
import time


class MyThreadUpdate(thread_update.Ui_MainWindow):
    def __init__(self):
        super(MyThreadUpdate, self).__init__()

    def retranslateUi(self, MainWindow):
        super(MyThreadUpdate, self).retranslateUi(MainWindow)
        ui.pushButton_2.clicked.connect(self.buttonsec_clicked)

    def buttonsec_clicked(self):
        chr_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        for element in chr_list:
            time.sleep(1)
            print(element)
        print('end')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = MyThreadUpdate()
    ui.setupUi(MainWindow)
    MainWindow.show()

    sys.exit(app.exec_())

会发现执行函数过程中UI界面卡死,如图所示:

 可以通过qt的QThread来解决。代码如下:

import thread_update
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import *
import sys, os
import time


class ButtonOne(QThread):
    def __init__(self):
        super(ButtonOne, self).__init__()

    def write(self, text):
        self.signalForText.emit(text)

    def run(self):
        for i in range(15):
            time.sleep(1)
            print(i)
        print('end')


class ButtonSec(QThread):
    def __init__(self):
        super(ButtonSec, self).__init__()

    def run(self):
        chr_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        for element in chr_list:
            time.sleep(1)
            print(element)
        print('end')


class MyThreadUpdate(thread_update.Ui_MainWindow):
    def __init__(self):
        super(MyThreadUpdate, self).__init__()
        self.thread_buttonsec = ButtonSec()
        self.thread_buttonone = ButtonOne()

    def retranslateUi(self, MainWindow):
        super(MyThreadUpdate, self).retranslateUi(MainWindow)
        ui.button_1.clicked.connect(self.buttonone_clicked)
        ui.pushButton_2.clicked.connect(self.buttonsec_clicked)

    def buttonone_clicked(self):
        self.thread_buttonone.start()

    def buttonsec_clicked(self):
        self.thread_buttonsec.start()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = MyThreadUpdate()
    ui.setupUi(MainWindow)
    MainWindow.show()

    sys.exit(app.exec_())

这样在点击按钮UI界面也不会卡顿。

下面实现将命令行输出重定向到UI界面上

import thread_update
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import *
import sys, os
import time


class ButtonOne(QThread):
    _signalForText = pyqtSignal(str)

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

    def write(self, text):
        self.signalForText.emit(text)

    def run(self):

        for i in range(15):
            time.sleep(1)
            print(i)
        print('end')

    @property
    def signalForText(self):
        return self._signalForText


class ButtonSec(QThread):
    def __init__(self):
        super(ButtonSec, self).__init__()

    def run(self):
        chr_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        for element in chr_list:
            time.sleep(1)
            print(element)
        print('end')


class MyThreadUpdate(thread_update.Ui_MainWindow):
    def __init__(self):
        super(MyThreadUpdate, self).__init__()
        self.thread_buttonsec = ButtonSec()
        self.thread_buttonone = ButtonOne()
        self.thread_buttonone.signalForText.connect(self.updateText)
        sys.stdout = self.thread_buttonone

    def retranslateUi(self, MainWindow):
        super(MyThreadUpdate, self).retranslateUi(MainWindow)
        ui.button_1.clicked.connect(self.buttonone_clicked)
        ui.pushButton_2.clicked.connect(self.buttonsec_clicked)

    def updateText(self, text):
        cursor = self.text_1.textCursor()
        cursor.insertText(text)
        self.text_1.setTextCursor(cursor)
        self.text_1.ensureCursorVisible()

    def buttonone_clicked(self):
        self.thread_buttonone.start()

    def buttonsec_clicked(self):
        self.thread_buttonsec.start()
        # chr_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        # for element in chr_list:
        #     time.sleep(1)
        #     print(element)
        # print('end')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = MyThreadUpdate()
    ui.setupUi(MainWindow)
    MainWindow.show()

    sys.exit(app.exec_())


实现效果如下:

 如果想要在1按钮函数运行结束之前,按钮处于不可点击状态也可以通过信号实现。简略代码如下

button1函数部分在添加一个信号,并在函数执行结束之后在发射

class ButtonOne(QThread):
    _signal = pyqtSignal()
    _signalForText = pyqtSignal(str)

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

    def write(self, text):
        self.signalForText.emit(text)

    def run(self):

        for i in range(15):
            time.sleep(1)
            print(i)
        print('end')
        self._signal.emit()

    @property
    def signalForText(self):
        return self._signalForText

UI界面部分代码,在点击按钮之后将按钮设为不可点击状态,同时在接收到信号时候将按钮设置为可以点击状态.

    def buttonone_clicked(self):
        self.button_1.setEnabled(False)
        self.thread_buttonone.start()
        self.thread_buttonone._signal.connect(self.enableButtonOne)

    def enableButtonOne(self):
        self.button_1.setEnabled(True)    

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值