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?