Reputation: 37
What I intended
Real work
I'm trying to use QThread for offloading the RSC function... but it looks not working.
Below is my code ↓
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_())
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()
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?
Upvotes: 1
Views: 548
Reputation: 17291
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.
Upvotes: 1