Answer the question
In order to leave comments, you need to log in
GUI freezes when executing a loop in a separate thread. How to fix?
Hello. Just started learning PyQt and I'm having a problem with threads. The matter is that I need, that in a separate flow the cycle which receives the data and displays in a window was executed. I wrote this code:
class ConfThread(QtCore.QThread):
def __init__(self, ex=None, parent=None):
super(ConfThread, self).__init__(parent)
self.test = ex
def __del__(self):
self.wait()
def conf(self):
while self.test.player.playing:
title = [self.test.player.source.info.title[:20]+'...' if len(self.test.player.source.info.title)>=9 else self.test.player.source.info.title, "Unknown"][self.test.player.source.info.title == '']
author = [self.test.player.source.info.author[:20], "Unknown"][self.test.player.source.info.author == '']
album = [self.test.player.source.info.album[:20], "Unknown"][self.test.player.source.info.album == '']
genre = [self.test.player.source.info.genre[:20], "Unknown"][self.test.player.source.info.genre == '']
tg.labTitle.setText(title)
tg.labArtist.setText(author)
tg.labArtist.setText(album)
tg.labYear.setText(genre)
tg.lab.setText(str(datetime.datetime.fromtimestamp(test.player.time).strftime('%M:%S')))
time.sleep(1)
def run(self):
self.conf()
while self.test.player.playing:
with if self.test.player.playing:
then, the GUI does not freeze, but I need the conf method to be called every second, not once when the thread starts. I tried to do it like this:def run(self):
timer = QtCore.QTimer()
timer.timeout.connect(self.conf)
timer.start(1000)
But this way conf is not called at all. def start():
th = ConfThread(ex=player)
th.start()
gui.connect(gui.butPlay, QtCore.SIGNAL('clicked()'), start)
Answer the question
In order to leave comments, you need to log in
Finally I found the answer. It turned out I was running the thread incorrectly. As far as I understood, this was due to the fact that I started the thread outside the PlayerGui class. Approximately such code of start of a flow at me turned out.
class PlayerGui(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, None)
self.th = ConfThread(ex='player')
self.lmain = QtGui.QGridLayout(self)
self.layout = QtGui.QGridLayout()
self.setGeometry(600, 300, 600, 500)
self.setMinimumSize(400, 450)
self.butPlay = QtGui.QPushButton("start", self)
self.layout.addWidget(self.butPlay,3, 0)
self.connect(self.butPlay, QtCore.SIGNAL("clicked()"), self.start)
self.lmain.addLayout(self.layout, 0,0)
def start(self):
self.th.start()
The Python interpreter has one feature: GIL . On the Internet you will find a lot of articles about what it is, and how the GIL helps / hinders writing multi-threaded applications.
In the case of using QTimer, the variable timer is local. This means that after the run(self) method completes, this variable will be destroyed and the timer will never fire. Try writing:
def run(self):
timer = QtCore.QTimer()
timer.timeout.connect(self.conf)
timer.start(1000)
self.timer = timer
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question