how to dynamically display widgets add to a QVBoxLayout pyside6

109 Views Asked by At

hi I’m designing a python project to practice a YouTube playlist downloader. for this I use python3 and pyside6 as a graphical interface but since a few hours I have a problem:

when I perform functions that take time (like searching for the url of a youtube playlist) freezes the entire interface until the processing is done so no access to the other components is possible.

but once the processing completes the function returns a number of widget-like component numbers from a class (videoGenerer) that inherits the widget component itself and which are all added to a QVBoxLayout type element with the addWidget() method (self.verticalLayout_6.addWidget(videoGenerer)) and then displayed on the screen.

disadvantages: the graphical interface remains frozen for a while waiting for the end of the method but I have my elements added in my QVBoxLayout (self.verticalLayout_6.addWidget(videoGenerer)) and visible on screen

The code is:

import os
import sys
import threading
from pathlib import Path

from PySide6 import QtWidgets
from PySide6.QtGui import QIcon
from PySide6.QtUiTools import loadUiType
from PySide6.QtWidgets import *
from pytube import Playlist
from pytube.exceptions import PytubeError

from composant.conteneurDeVideo import conteneurDeVideo

path = os.fspath(Path(__file__).resolve().parent / "main.ui")
Form, _ = loadUiType(path)


class main(QMainWindow, Form):

    def __init__(self, parent=None):
        super(main, self).__init__(parent)
        self.setupUi(self)
        # ------------ commencer en dessou -----------
        self.setWindowTitle("PlayList")
        self.setWindowIcon(QIcon("icons/_active__web.png"))
        self.resize(1200, 600)

        self.btnRechercher.clicked.connect(self.threadMethode)

    def threadMethode(self):
        threadRecherchePlaylist = threading.Thread(target=self.recherchePlaylist())
        threadRecherchePlaylist.start()

    def recherchePlaylist(self):

        self.txtUrl: str = self.editUrl.text()
        self.videosPlaylist = Playlist(self.txtUrl.strip())

        for video in self.videosPlaylist.videos:
            try:

                print(threading.active_count())
                print(threading.enumerate())

                videoGenerer = conteneurDeVideo(video)

                self.verticalLayout_6.addWidget(videoGenerer)

            except PytubeError:
                print("impossible de recuperer cette video...")

        print("elemment ajouter ", self.verticalLayout_6.count())


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = main()
    w.show()  # show window
    sys.exit(app.exec())

to solve my screen problem freeze I told myself better to put this function in another thread to not block the main thread and since all is done correctly I even checked the two threads are executed I am no longer the GUI freeze and all my elements are always added in my QVBoxLayout with the addWidget() method (I checked it too) but this time I no longer have any visible elements on the screen and I have no errors in the console either

The code is:

import os
import sys
import threading
from pathlib import Path

from PySide6 import QtWidgets
from PySide6.QtGui import QIcon
from PySide6.QtUiTools import loadUiType
from PySide6.QtWidgets import *
from pytube import Playlist, YouTube
from pytube.exceptions import PytubeError

from composant.conteneurDeVideo import conteneurDeVideo

path = os.fspath(Path(__file__).resolve().parent / "main.ui")
Form, _ = loadUiType(path)


class main(QMainWindow, Form):

    def __init__(self, parent=None):
        super(main, self).__init__(parent)
        self.setupUi(self)
        # ------------ commencer en dessou -----------
        self.setWindowTitle("PlayList")
        self.setWindowIcon(QIcon("icons/_active__web.png"))
        self.resize(1200, 600)

        self.btnRechercher.clicked.connect(self.threadMethode)

    def threadMethode(self):

        self.txtUrl: str = self.editUrl.text()
        self.videosPlaylist = Playlist(self.txtUrl.strip())

        def recherchePlaylist():
            for video in self.videosPlaylist.videos:
                try:

                    print("nbr des thread activer", threading.active_count())
                    print("liste de thread active", threading.enumerate())

                    videoGenerer = conteneurDeVideo(video)

                    self.verticalLayout_6.addWidget(videoGenerer)

                except PytubeError:
                    print("impossible de recuperer cette video...")

            print("elemment ajouter ", self.verticalLayout_6.count())

        threadRecherchePlaylist = threading.Thread(target=recherchePlaylist, args=())
        threadRecherchePlaylist.start()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = main()
    w.show()  # show window
    sys.exit(app.exec())

the class (videoGenerer) that returns the widgets:

import os
from pathlib import Path
import sys

from PySide6.QtWidgets import *
from PySide6.QtUiTools import loadUiType
from PySide6 import QtWidgets
from pytube import YouTube

path = os.fspath(Path(__file__).resolve().parent / "conteneurDeVideo.ui")
Form, _ = loadUiType(path)


class conteneurDeVideo(QWidget, Form):

    def __init__(self, video: YouTube, parent=None):
        super(conteneurDeVideo, self).__init__(parent)
        self.setupUi(self)
        # ------------ commencer en dessou -----------

        self.video = video

        txt: QLabel = self.label
        txt.setText(video.title)

    def pourcent(self, stream, chunk, byte_remaning):
        nbr = stream.filesize - byte_remaning
        print("progress", int(nbr * 100 / stream.filesize), "%")

    def telecharger(self):
        self.video.register_on_progress_callback(self.pourcent)
        tag_de_telechargement = self.video.streams.get_by_itag(22)

        print("telechargement lancer...")
        chemins = os.path.join("C:\\Users\\pc\\Desktop", "youVideo")
        os.makedirs(chemins, exist_ok=True)
        tag_de_telechargement.download(chemins)

I have no idea to display them on the screen without freezing the entire interface (do not block the main thread) do you have any solutions to offer me?

0

There are 0 best solutions below