我对编程很生疏,对Python和ttkbootstrap一点也不熟悉,但我尽力了。
我创建了一个小实用程序来下载 YouTube 视频,它基本上可以工作,这意味着它可以下载所选目录中的视频。但是,下载时进度条不会更新,并且百分比文本最后显示 100%,下载时不会更新。
如果您能帮助我改进我的代码,并使事情按照我认为应该的方式工作,我将非常感激...
到目前为止,这是我的代码
import pathlib
from tkinter import ttk
import ttkbootstrap as ttkb
from ttkbootstrap.constants import *
import ttkbootstrap.style
from tkinter.filedialog import askdirectory
from pytube import YouTube
class DataEntryForm(ttkb.Frame):
def __init__(self, master):
super().__init__(master, padding=(20,10))
self.pack(fill =BOTH, expand=YES)
#application variables
self.repertoireChoisi = ttkb.StringVar()
#self._path = pathlib.Path().absolute().as_posix()
#form variables
self.URL = ttkb.StringVar(value="")
self.repertoire = ttkb.StringVar(value="" )
self.percentage_of_completion = ttkb.StringVar(value="0%")
#form header
hdr_txt = "Entrez l'URL de la vidéo et le répertoire où les fichiers seront stockés"
hdr = ttkb.Label(self, text=hdr_txt, width= 100)
hdr.pack(fill = X, padx=10, pady=10)
#form entries
self.create_form_entry("url", self.URL)
self.create_progressbar(0)
self.create_repertoire_entry("repertoire", self.repertoire)
self.create_buttonbox()
def create_form_entry(self, label, variable):
"""Create a single form entry"""
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=5)
lbl = ttkb.Label(master=container, text=label.title(), width=10)
lbl.pack(side=LEFT, padx=5)
ent = ttkb.Entry(master=container, textvariable=self.URL, width = 80)
ent.pack(side=LEFT, padx=5, fill=X, expand=YES)
rep_button = ttkb.Button(
master = container,
text = "Télécharger",
style=SUCCESS,
command = self.on_download,
width= 20
)
rep_button.pack(side=LEFT, padx=5, fill=X, expand=NO)
def create_repertoire_entry(self, label, variable):
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=5)
lbl = ttkb.Label(master=container, text="Repertoire", width=10)
lbl.pack(side=LEFT, padx=5)
#self.create_form_entry("repertoire", self.repertoire)
ent = ttkb.Entry(master=container, width=80, textvariable=variable)
ent.pack(side=LEFT, padx=5, fill=X, expand=NO)
rep_button = ttkb.Button(
master = container,
text = "Rechercher",
style=SUCCESS,
command = self.on_search,
width= 20
)
rep_button.pack(side=LEFT, padx=5, fill=X, expand=NO)
def create_progressbar(self, percent):
"""Create a progress bar"""
# progress = ttkb.Frame(self,style=PRIMARY)
#container = ttkb.Frame(self)
progress = ttk.Progressbar(self)
progress.pack(fill=X,expand=YES, pady=(15,10))
# self.time_elapsed = ttk.Label(progress, text='00:00', font='Helvetica 12')
# self.time_elapsed.pack(side='left')
# self.time_scale = ttk.Scale(progress, orient='horizontal', style='info.Horizontal.TScale')
# self.time_scale.pack(side='left', expand=True, padx=10)
# self.time_remaining = ttk.Label(progress, text='00:00', font='Helvetica 12')
# self.time_remaining.pack(side='right')
self.percentage_of_completion = ttk.Label(self, width = 40, text=str(percent) + "%")
self.percentage_of_completion.pack(fill=BOTH, expand=TRUE, padx = 215)
def create_buttonbox(self):
"""Create the application buttonbox"""
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=(15, 10))
sub_btn = ttkb.Button(
master=container,
text="Envoyer",
command=self.on_submit,
style =SUCCESS,
width=10,
)
sub_btn.pack(side=RIGHT, padx=5)
sub_btn.focus_set()
cnl_btn = ttkb.Button(
master=container,
text="Cancel",
command=self.on_cancel,
style=DANGER,
width=10,
)
cnl_btn.pack(side=RIGHT, padx=5)
def on_submit(self):
"""Print the contents to console and return the values."""
print("URL:", self.URL.get())
print("repertoire:", self.repertoire.get())
return self.URL.get(), self.repertoire.get()
def on_cancel(self):
"""Cancel and close the application."""
self.quit()
def on_search(self):
"""Search directory where to download the files."""
#self.repertoire = askdirectory()
self.repertoireChoisi.set(askdirectory(
initialdir="/",
title="Sélectionnez un répertoire"
)
)
self.repertoire.set(self.repertoireChoisi.get())
def on_download(self):
"""get data from the video and dl it."""
video = YouTube(self.URL.get())
filters = video.streams.filter(file_extension='mp4')
mp4_720 = filters.get_highest_resolution()
# récupérer les infos de la vidéo ici
# description = video.description
# length = video.length # video length in seconds
video.register_on_progress_callback(self.on_progress)
mp4_720.download(self.repertoire.get())
# filters = video.streams.filter(file_extension='mp4')
# mp4_1080 = filters.get_highest_resolution()
# mp4_1080.download(self.repertoire.get(), 'test2.mp4')
def on_progress(self, stream, chunk, bytes_remaining):
"""Update the progress bar."""
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
self.percentage_of_completion.config(text=str((bytes_downloaded / total_size) * 100))
if __name__ == "__main__":
app = ttkb.Window("Téléchargement de Vidéo YouTube", "superhero", resizable=(False, False))
#app.geometry("500x400")
DataEntryForm(app)
app.mainloop()
# root = ttkb.Window(themename="darkly")
# b1 = ttkb.Button(root, text='Bouton Un', bootstyle = SUCCESS)
# b1.pack(side= LEFT, padx=5, pady = 10)
# b2 = ttkb.Button(root, text='Bouton Deux', bootstyle = (INFO, OUTLINE))
# b2.pack(side=LEFT,padx=5, pady =10)
# root.mainloop()
在此处找到的以下示例中,我尝试了不同的组合来从“on_progress”更新进度条,但我想我遗漏了一些明显的东西。 (或者这应该是显而易见的,但对我来说不是):-)
感谢您的帮助, 伯纳德
我终于成功了。 首先,我注册回调的语法不正确。看起来必须这样做:
video = YouTube(self.URL.get(), on_progress_callback=self.on_progress)
而且我不知道进度更新方法
self.progress.update()
所以现在可以正常工作了。需要清理,但这现在是一个可以运行的小实用程序。最终这可以帮助其他人:
import pathlib
from tkinter import ttk
import ttkbootstrap as ttkb
from ttkbootstrap.constants import *
import ttkbootstrap.style
from tkinter.filedialog import askdirectory
from pytube import YouTube
import time
class DataEntryForm(ttkb.Frame):
def __init__(self, master):
super().__init__(master, padding=(20,10))
self.pack(fill =BOTH, expand=YES)
#application variables
self.repertoireChoisi = ttkb.StringVar()
self.stuff = ttkb.IntVar()
#self._path = pathlib.Path().absolute().as_posix()
#form variables
self.URL = ttkb.StringVar(value="")
self.repertoire = ttkb.StringVar(value="" )
self.percentage_of_completion = ttkb.StringVar(value="0%")
#form header
hdr_txt = "Entrez l'URL de la vidéo et le répertoire où les fichiers seront stockés"
hdr = ttkb.Label(self, text=hdr_txt, width= 100)
hdr.pack(fill = X, padx=10, pady=10)
#form entries
self.create_form_entry("url", self.URL)
self.create_progressbar(0)
self.create_repertoire_entry("repertoire", self.repertoire)
self.create_buttonbox()
def create_form_entry(self, label, variable):
"""Create a single form entry"""
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=5)
lbl = ttkb.Label(master=container, text=label.title(), width=10)
lbl.pack(side=LEFT, padx=5)
ent = ttkb.Entry(master=container, textvariable=self.URL, width = 80)
ent.pack(side=LEFT, padx=5, fill=X, expand=YES)
rep_button = ttkb.Button(
master = container,
text = "Télécharger",
style=SUCCESS,
command = self.on_download,
width= 20
)
rep_button.pack(side=LEFT, padx=5, fill=X, expand=NO)
def create_repertoire_entry(self, label, variable):
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=5)
lbl = ttkb.Label(master=container, text="Repertoire", width=10)
lbl.pack(side=LEFT, padx=5)
#self.create_form_entry("repertoire", self.repertoire)
ent = ttkb.Entry(master=container, width=80, textvariable=variable)
ent.pack(side=LEFT, padx=5, fill=X, expand=NO)
rep_button = ttkb.Button(
master = container,
text = "Rechercher",
style=SUCCESS,
command = self.on_search,
width= 20
)
rep_button.pack(side=LEFT, padx=5, fill=X, expand=NO)
def create_progressbar(self, percent):
"""Create a progress bar"""
# progress = ttkb.Frame(self,style=PRIMARY)
#container = ttkb.Frame(self)
self.progress = ttkb.Progressbar(self, style=PRIMARY,maximum = 100.00, mode=DETERMINATE)
self.progress.pack(fill=X,expand=YES, pady=(15,10))
# self.time_elapsed = ttk.Label(progress, text='00:00', font='Helvetica 12')
# self.time_elapsed.pack(side='left')
# self.time_scale = ttk.Scale(progress, orient='horizontal', style='info.Horizontal.TScale')
# self.time_scale.pack(side='left', expand=True, padx=10)
# self.time_remaining = ttk.Label(progress, text='00:00', font='Helvetica 12')
# self.time_remaining.pack(side='right')
self.percentage_of_completion = ttk.Label(self, width = 40, text=str(percent) + "%")
self.percentage_of_completion.pack(fill=BOTH, expand=TRUE, padx = 215)
def create_buttonbox(self):
"""Create the application buttonbox"""
container = ttkb.Frame(self)
container.pack(fill=X, expand=YES, pady=(15, 10))
sub_btn = ttkb.Button(
master=container,
text="Envoyer",
command=self.on_submit,
style =SUCCESS,
width=10,
)
sub_btn.pack(side=RIGHT, padx=5)
sub_btn.focus_set()
cnl_btn = ttkb.Button(
master=container,
text="Cancel",
command=self.on_cancel,
style=DANGER,
width=10,
)
cnl_btn.pack(side=RIGHT, padx=5)
def on_submit(self):
"""Print the contents to console and return the values."""
print("URL:", self.URL.get())
print("repertoire:", self.repertoire.get())
return self.URL.get(), self.repertoire.get()
def on_cancel(self):
"""Cancel and close the application."""
self.quit()
def on_search(self):
"""Search directory where to download the files."""
#self.repertoire = askdirectory()
self.repertoireChoisi.set(askdirectory(
initialdir="/",
title="Sélectionnez un répertoire"
)
)
self.repertoire.set(self.repertoireChoisi.get())
def on_download(self):
"""get data from the video and dl it."""
video = YouTube(self.URL.get(), on_progress_callback=self.on_progress)
filters = video.streams.filter(file_extension='mp4')
mp4_720 = filters.get_highest_resolution()
# récupérer les infos de la vidéo ici
# description = video.description
# length = video.length # video length in seconds
#video.register_on_progress_callback= self.on_progress
mp4_720.download(self.repertoire.get())
# filters = video.streams.filter(file_extension='mp4')
# mp4_1080 = filters.get_highest_resolution()
# mp4_1080.download(self.repertoire.get(), 'test2.mp4')
def on_progress(self, stream, chunk, bytes_remaining):
"""Update the progress bar."""
#percent = (bytes_remaining / stream.filesize) * 100
total_size = stream.filesize
#self.stuff += chunk
bytes_downloaded = total_size - bytes_remaining
self.percentage_of_completion.config(text=str(round((bytes_downloaded / total_size) * 100,2)) + "%")
self.progress['value'] = round((bytes_downloaded / total_size) * 100,2)
self.progress.update()
if __name__ == "__main__":
app = ttkb.Window("Téléchargement de Vidéo YouTube", "superhero", resizable=(False, False))
#app.geometry("500x400")
DataEntryForm(app)
app.mainloop()