Search code examples
pythonmultithreadingpyqt5qthread

How can i stop QThread from repeating function in python PyQt5?


I am using pafy module to download youTube videos, when i click Get quality button it woks perfectly for the fist time, but when try to get quality for another video the function repeated sometimes.

Get Quality Button will get the name and quality of videos

if i use terminate() it will not work for the second time...

my entire code and widget.ui here: https://pastebin.com/0kityt79

look at these pictures you will understand what i mean.

The first time when i click Get Quality

the second time when i clicked Get Quality

class KYD(QWidget,myui):

    urlSignal = pyqtSignal(str)

    def __init__(self,parent=None):
        super(QWidget,self).__init__(parent)

        self.get_quality_btn.clicked.connect(self.getQuality_vdieos)


        self.worker=workers()
        self.mythread=QThread()

    def getQuality_vdieos(self):
        try:
            url=self.Url.text()
            self.worker.moveToThread(self.mythread)
            self.urlSignal.connect(self.worker.qualities)
            self.urlSignal.emit(url) #this will send url to workers class,qualities function

            self.mythread.start()

            self.worker.info.connect(self.information)#this will send the title of the videos to the QTreeView

            self.worker.urlLink.connect(self.insertQulaity)

        except Exception as e:
            print(str(e))

    def insertQulaity(self,values):
        try:
            for qualities in values:
                self.chooseQuality.addItem(str(qualities),qualities)
        except Exception as e:
            print(str(e))

Class workers(QObject)

    info=pyqtSignal(str)
    urlLink=pyqtsignal(list)

    def __init__(self):
        super().__init__()

    def qualities(self, url):
        try:
            if url !='':
                self.source = pafy.new(url)
                self.videos_streams = self.source.videostreams
                self.info.emit(self.source.title) #this will send title to TreeView
                for self.videos in self.videos_streams:
                    size=humanize.naturalsize(self.videos.get_filesize())
                    data=['{}     {}     {}'.format(self.videos.resolution,self.videos.extension,size)]  
                    self.urlLink.emit(data) #this will send quality to Combobox

        except Exception as e:
            print(str(e))

Solution

  • The problem is not with the QThread part, but rather with the fact that every time you click the button you are adding signal-slot connections between the workers and QYD objects. Just create all the connections you need in QYD.__init__ instead of QYD.getQuality. Also, you don't have to start the thread, nor move the worker to the thread every time you press the button so you can move all that to QYD.__init__ as well. So in summary, QYD should be something like

    class KYD(QWidget,myui):
    
        urlSignal = pyqtSignal(str)
    
        def __init__(self,parent=None):
            super(QWidget,self).__init__(parent)
    
            self.get_quality_btn.clicked.connect(self.getQuality_vdieos)
    
            self.mythread=QThread()
            self.worker=workers()
            self.worker.moveToThread(self.mythread)
    
            self.worker.info.connect(self.information)
            self.worker.urlLink.connect(self.insertQulaity)
            self.urlSignal.connect(self.worker.qualities)
    
            self.mythread.start()
    
        def getQuality_vdieos(self):
            try:
                url=self.Url.text()
                self.urlSignal.emit(url) 
            except Exception as e:
                print(str(e))