Question:
There is a function (LoadData) for loading big data (taken from the database (SQlite)) into a text file ( fout ) with filling in the corresponding indicator ( self.ui.progressBar ). When the function is executed, the window application starts "Do not respond" and freezes (since the cycle time is ~ 3 minutes, depending on the size of data ) while the cycle ( for line in data ) is executed. Accordingly, the indicator value is 0% all this time. What are the options for solving this problem?
def LoadData(self, data):
nof = self.ui.lineEdit_22.text() + '.txt' #Имя файла вводит пользователь
fout = open(nof, 'w')
self.step = 0 #Значение индикатора
percent = len(data)/100 #Количество строк в 1%
coun = 0 #Счётчик строк
for line in data:
for i in range(10):
fout.write(str(line[i]))
fout.write(' ')
fout.write('\n')
coun = coun + 1
if coun == percent:
coun = 0
self.step = self.step + 1
self.ui.progressBar.setValue(self.step)
fout.close()
Answer:
Start long process in QThread:
import sys
import time
from PyQt5 import QtCore, QtWidgets
class SlowTask(QtCore.QThread):
updated = QtCore.pyqtSignal(int)
running = False
def __init__(self, *args, **kwargs):
super(SlowTask, self).__init__(*args, **kwargs)
self.percent = 0
self.running = True
def run(self):
while self.running:
self.percent += 1
self.percent %= 100
self.updated.emit(int(self.percent))
time.sleep(0.1)
def stop(self):
self.running = False
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi()
def setupUi(self):
self.setWindowTitle('Test')
self.resize(446, 207)
self.progressbar = QtWidgets.QProgressBar(self)
self.progressbar.setGeometry(QtCore.QRect(40, 70, 381, 23))
self.progressbar.setProperty('value', 0)
self.btn_start = QtWidgets.QPushButton('Start', self)
self.btn_start.setGeometry(QtCore.QRect(110, 110, 75, 23))
self.btn_start.setEnabled(True)
self.btn_start.clicked.connect(self.on_start)
self.btn_stop = QtWidgets.QPushButton('Stop', self)
self.btn_stop.setGeometry(QtCore.QRect(260, 110, 75, 23))
self.btn_stop.setEnabled(False)
self.btn_stop.clicked.connect(self.on_stop)
def toggle_buttons(self):
self.btn_start.setEnabled(not self.btn_start.isEnabled())
self.btn_stop.setEnabled(not self.btn_stop.isEnabled())
def on_update(self, data):
self.progressbar.setValue(data)
# if data == 99:
# self.on_stop()
def on_start(self):
self.toggle_buttons()
self.task = SlowTask(self)
self.task.updated.connect(self.on_update)
self.task.start()
def on_stop(self):
self.task.stop()
self.progressbar.setValue(0)
self.toggle_buttons()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())