简体   繁体   中英

pyqt5) GUI still freezing even though using QThread

What I intended

  • when I click 'start' button on Subwindow then loading logo animation starts, and RSC function(Long running function) works separately.

Real work

  • when I click the "start" button, the RSC function works but gui freezes.

I'm trying to use QThread for offloading the RSC function... but it looks not working.

Below is my code ↓

  1. Main Window(1st window)

     # -*- coding: utf-8 -*- from PyQt5 import QtCore, QtWidgets from Sub import SubWindow from Last import LastWindow from functools import partial import sys class Main_Window(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.resize(800, 600) self.initUI() def initUI(self): # next pushbutton self.pb_next = QtWidgets.QPushButton(self) self.pb_next.setGeometry(QtCore.QRect(540, 480, 112, 34)) self.pb_next.setText('Next') self.pb_next.clicked.connect(self.CallSub) # quit pushbutton self.pb_quit = QtWidgets.QPushButton(self) self.pb_quit.setGeometry(QtCore.QRect(660, 480, 112, 34)) self.pb_quit.setText('Quit') self.pb_quit.clicked.connect(QtCore.QCoreApplication.instance().quit) def CallSub(self): self.hide() self.SW = SubWindow() self.SW.show() print('call sub') self.SW.PB.clicked.connect(self.SW.Loading) print('loading') self.SW.PB.clicked.connect(self.RSC) print('rsc') def RSC(self): print('start rsc') self.text1 = 'host.txt' self.text2 = 'access.txt' self.thread = QtCore.QThread() self.SW.moveToThread(self.thread) self.thread.started.connect(partial(self.SW.RunSecurityCheck,self.text1,self.text2)) self.SW.finished.connect(self.thread.quit) self.SW.finished.connect(self.SW.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.SW.finished.connect(self.CallLast) self.thread.start() def CallLast(self): self.LW = LastWindow() self.SW.hide() self.LW.show() self.LW.pb_next.clicked.connect(self.CallMain) def CallMain(self): self.LW.hide() self.show() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) mw = Main_Window() mw.show() sys.exit(app.exec_())
  2. Sub Window(2nd window)

     # -*- coding: utf-8 -*- from time import sleep from PyQt5 import QtCore, QtWidgets, QtGui class SubWindow(QtWidgets.QWidget): finished = QtCore.pyqtSignal() def __init__(self): super().__init__() self.resize(800, 600) self.initUI() def initUI(self): # Quit PushButton self.pb_quit = QtWidgets.QPushButton(self) self.pb_quit.setGeometry(QtCore.QRect(660, 480, 112, 34)) self.pb_quit.setText('Quit') self.pb_quit.clicked.connect(QtCore.QCoreApplication.instance().quit) # start push button self.PB = QtWidgets.QPushButton(self) self.PB.setGeometry(QtCore.QRect(280, 240, 100, 25)) self.PB.setText('Start') # loading animation self.LB_loading = QtWidgets.QLabel(self) self.LB_loading.setGeometry(QtCore.QRect(250, 210, 200, 100)) self.loading = QtGui.QMovie("loading.gif") self.LB_loading.setMovie(self.loading) self.LB_loading.hide() def Loading(self): self.PB.hide() self.LB_loading.show() self.loading.start() def RunSecurityCheck(self,t1,t2): sleep(10) self.finished.emit()
  3. Last window(3rd window)

     # -*- coding: utf-8 -*- from PyQt5 import QtCore, QtWidgets class LastWindow(QtWidgets.QWidget): def __init__(self): super().__init__() self.resize(800, 600) self.initUI() def initUI(self): # Next PushButton self.pb_next = QtWidgets.QPushButton(self) self.pb_next.setGeometry(QtCore.QRect(540, 480, 112, 34)) self.pb_next.setText('Back to Main') # Quit PushButton self.pb_quit = QtWidgets.QPushButton(self) self.pb_quit.setGeometry(QtCore.QRect(660, 480, 112, 34)) self.pb_quit.setText('Quit') self.pb_quit.clicked.connect(QtCore.QCoreApplication.instance().quit) # complete label self.LB1 = QtWidgets.QLabel(self) self.LB1.setGeometry(QtCore.QRect(140, 220, 221, 18)) self.LB1.setText('Complete.')

and below is my loading.gif file

在此处输入图像描述

how could I fix the gui freezing?

As stated in musicamante's comment routines run in a separate thread need to be independent of the GUI. So what probably makes the most sense in your situation would be to subclass QThread and make RunSecurityCheck a method of the QThread , and pass in your two text parameters to the constructor of the thread. Then the code that is responsible for freezing the GUI will be run separately and will no longer cause freezing/stalling.

For Example:

in your 1st window file you can make some minor changes to RSC method and import the Thread subclass

from Sub import SubWindow, Thread

...

    def RSC(self):
        print('start rsc')
        self.text1 = 'host.txt'
        self.text2 = 'access.txt'
        self.thread = Thread(self.text1, self.text2)
        self.thread.finished.connect(self.thread.quit)
        self.thread.finished.connect(self.SW.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.finished.connect(self.CallLast)
        self.thread.start()

...

Then in your Sub.py

class SubWindow(QtWidgets.QWidget) :
    finished = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        self.resize(800, 600)
        self.initUI()

    def initUI(self):
        # Quit PushButton
        self.pb_quit = QtWidgets.QPushButton(self)
        self.pb_quit.setGeometry(QtCore.QRect(660, 480, 112, 34))
        self.pb_quit.setText('Quit')
        self.pb_quit.clicked.connect(QtCore.QCoreApplication.instance().quit)
        # start push button
        self.PB = QtWidgets.QPushButton(self)
        self.PB.setGeometry(QtCore.QRect(280, 240, 100, 25))
        self.PB.setText('Start')
        # loading animation
        self.LB_loading = QtWidgets.QLabel(self)
        self.LB_loading.setGeometry(QtCore.QRect(250, 210, 200, 100))
        self.loading = QtGui.QMovie("loading.gif")
        self.LB_loading.setMovie(self.loading)
        self.LB_loading.hide()

    def Loading(self):
        self.PB.hide()
        self.LB_loading.show()
        self.loading.start()


class Thread(QtCore.QThread):

    def __init__(self, t1, t2):
        super().__init__()
        self.t1 = t1
        self.t2 = t2

    def RunSecurityCheck(self,t1,t2):
        sleep(10)

    def run(self):
        self.RunSecurityCheck(self.t1, self.t2)
        self.finished.emit()

Your last file doesn't require any changes.

All you need to do is make those few minor changes and Bob's your uncle. It should work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM