R
R
Ruben Harutyunov2014-07-17 12:42:30
Python
Ruben Harutyunov, 2014-07-17 12:42:30

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()

But when starting the thread, the GUI freezes.
If replaced 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.
Help me please. With PyQt and creating graphs. the interface had no business earlier.
UPD:
Stream starts when button is clicked
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

3 answer(s)
R
Ruben Harutyunov, 2014-07-17
@K_DOT

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()

S
sheknitrtch, 2014-07-17
@sheknitrtch

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

S
Sergei Borisov, 2014-07-17
@risik

And show how exactly you start the stream

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question