[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk
import threading
import requests
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
import time
from PIL import Image, ImageTk
def download_file(url, save_path, progress_callback):
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
progress_bar = tqdm(total=total_size, unit='B', unit_scale=True, desc=f"Downloading {url}")
with open(save_path, 'wb') as file:
for data in response.iter_content(1024):
file.write(data)
progress_bar.update(len(data))
if progress_callback:
progress_callback(len(data))
progress_bar.close()
def start_download(urls, save_paths, progress_callback):
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(download_file, url, save_path, progress_callback) for url, save_path in zip(urls, save_paths)]
for future in futures:
future.result()
def create_window():
root = tk.Tk()
root.title("多线程下载器")
root.geometry("420x211")
# 设置无边框窗口
root.overrideredirect(True)
# 加载背景图片
background_image = Image.open("./2.png")
background_photo = ImageTk.PhotoImage(background_image)
# 创建一个标签来显示背景图片
background_label = tk.Label(root, image=background_photo)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
background_label.image = background_photo
# 添加一个进度条
progress = ttk.Progressbar(root, orient="horizontal", length=300, mode="determinate")
progress.pack(pady=20)
progress.place(x=60, y=150)
info_label = tk.Label(root, text="", bg="white") # 设置背景颜色以区分
info_label.pack(pady=10)
info_label.place(x=80, y=180)
start_time = 0
last_speed = 0
close_button_image = Image.open("./close.png").convert("RGBA")
close_button_photo = ImageTk.PhotoImage(close_button_image)
close_button = tk.Button(root, image=close_button_photo, bd=0, highlightthickness=0, command=root.destroy)
close_button.image = close_button_photo # 保持对图片的引用
close_button.place(x=390, y=0) # 调整 x 和 y 的值以适应你的窗口布局
def update_progress(value):
nonlocal last_speed
progress["value"] += value
root.update_idletasks()
# 更新详细信息
total_size = progress["maximum"]
downloaded_size = progress["value"]
remaining_bytes = total_size - downloaded_size
if remaining_bytes > 0 and value > 0:
current_time = time.time()
elapsed_time = current_time - start_time
speed = downloaded_size / elapsed_time
remaining_time = remaining_bytes / speed
# 计算百分比变化
if last_speed > 0:
speed_change = (speed - last_speed) / last_speed * 100
else:
speed_change = 0
info_label.config(text=f"{downloaded_size / (1024 * 1024):.2f}MB/{total_size / (1024 * 1024):.2f}MB 速度{speed / (1024 * 1024):.2f}MB/s 还要{remaining_time:.0f}秒")
else:
info_label.config(text="")
last_speed = speed
def on_start_download():
nonlocal start_time, last_speed
start_time = time.time()
last_speed = 0
urls = [
"https://pcpackagebssdlbig.kugou.com/202412062152/816eead6453db1a20061690cb2e36eff/web/kugou_release_20010.exe"
]
save_paths = [
"c:/Users/win/Desktop/file1.exe"
]
# 计算总文件大小
total_size = sum(int(requests.head(url).headers.get('content-length', 0)) for url in urls)
progress["maximum"] = total_size
progress["value"] = 0
# 实际下载任务
threading.Thread(target=start_download, args=(urls, save_paths, update_progress)).start()
start_button = tk.Button(root, text="开始下载", command=on_start_download)
start_button.pack(pady=20)
start_button.place(x=180, y=110) # 调整 x 和 y 的值
# 保持对背景图片的引用
background_label.image = background_photo
# 拖动窗体
def on_drag_start(event):
root._drag_start_x = event.x
root._drag_start_y = event.y
def on_drag_motion(event):
x = root.winfo_x() + event.x - root._drag_start_x
y = root.winfo_y() + event.y - root._drag_start_y
root.geometry(f"+{x}+{y}")
def on_drag_release(event):
pass
background_label.bind("<Button-1>", on_drag_start)
background_label.bind("<B1-Motion>", on_drag_motion)
background_label.bind("<ButtonRelease-1>", on_drag_release)
root.mainloop()
if __name__ == "__main__":
create_window()