You need to enable JavaScript to run this app. Tkinter Scrollbar滚动时GUI冻结问题求助:Selenium文件下载工具故障
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter Scrollbar滚动时GUI冻结问题求助:Selenium文件下载工具故障

Tkinter+Selenium文件列表GUI滚动冻结修复方案

核心故障原因

  • Tkinter所有UI操作必须在主线程执行,原代码在子线程中直接创建Label、Button等组件、调用布局方法,触发线程冲突导致冻结
  • 无意义的res死循环线程每秒执行上亿次scrollregion更新,CPU占满后GUI完全无响应
  • 循环内重复调用pack方法、反复执行list.index()遍历,大量冗余操作拖慢运行效率
  • 下载按钮存在闭包陷阱,所有按钮会默认绑定最后一个文件的下载地址

修复方案

具体修改点

  • 删除无用的res死循环线程,仅在所有列表元素加载完成后更新一次scrollregion
  • 所有UI创建、布局操作通过root.after()抛到主线程执行,规避线程安全问题
  • 去掉循环内冗余的pack调用,优化遍历逻辑直接用索引取值,避免重复遍历列表
  • 修正闭包陷阱,确保每个下载按钮绑定对应文件的地址
  • 下载链接动态拼接,不再硬编码固定前缀,适配不同输入URL
  • 新增chromedriver自动关闭逻辑,避免后台进程残留

修复后完整代码

import tkinter as tk
import tkinter.font as font
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from threading import Thread
import webbrowser
import time

root = tk.Tk()
root.geometry("640x480")
root.state("zoom")

tk.Label(root, text="URL:", font=font.Font(size=20)).place(x=20, y=20)
url_input = tk.Entry(root, font=font.Font(size=20))
url_input.place(x=20, y=60, width=490, height=40)

urls = []
result = []
result_b = []

main_frame = tk.LabelFrame(root)
canvas = tk.Canvas(main_frame, highlightbackground="gray")
canvas.pack(side=tk.LEFT, fill="both", expand="yes")

v_scroll_bar = tk.Scrollbar(main_frame, orient="vertical", command=canvas.yview)
v_scroll_bar.pack(side=tk.RIGHT, fill="y")
canvas.configure(yscrollcommand=v_scroll_bar.set)

def update_scrollregion(event):
    canvas.configure(scrollregion=canvas.bbox("all"))
canvas.bind("<Configure>", update_scrollregion)

result_frame = tk.Frame(canvas)
canvas.create_window((0, 0), window=result_frame, anchor="nw")
main_frame.pack(fill="both", expand="yes")

def download_links(links, base_url):
    global urls
    urls = links
    # UI操作提交到主线程执行
    def render_ui():
        for idx, l in enumerate(links):
            file_name = l.find_elements_by_css_selector("*")[0].get_attribute("title")
            lLabel = tk.Label(result_frame, font=font.Font(size=20), text=f"{idx+1}.{file_name}")
            lLabel.grid(row=idx, column=0, sticky=tk.W)

            lDownloadB = tk.Button(result_frame, text="Download")
            lDownloadB.grid(row=idx, column=1, sticky=tk.E, ipadx=10, ipady=5)
            
            # 修正闭包陷阱,直接传入当前文件名
            def dl(e, file=file_name):
                base_path = base_url.split("0:/")[0]
                durl = f"{base_path}0:down/_Alvro%20Collection/{file}"
                webbrowser.open_new(durl)
            lDownloadB.bind("<ButtonRelease-1>", dl)

            result.append(lLabel)
            result_b.append(lDownloadB)
        # 所有元素加载完成后更新一次滚动区域
        update_scrollregion(None)
    root.after(0, render_ui)

def scrap():
    global d
    input_url = url_input.get().strip()
    if not input_url:
        return
    options = Options()
    options.headless = True
    # 屏蔽控制台多余日志输出
    options.add_experimental_option('excludeSwitches', ['enable-logging'])
    d = Chrome(executable_path="chromedriver.exe", options=options)
    d.get(input_url)

    def func():
        time.sleep(2)
        while True:
            time.sleep(0.1)
            links = d.find_elements_by_css_selector("#app > div > section > div > div > div.golist > table > tbody > tr")
            if len(links) > 50:
                download_links(links, input_url)
                d.quit() # 数据抓取完成后自动关闭浏览器进程
                break
            else:
                d.refresh()
    t = Thread(target=func, daemon=True)
    t.start()

scarp_b = tk.Button(root, text="Get", font=font.Font(size=20), command=scrap)
scarp_b.place(x=510, y=60, width=100, height=40)

def conf(e):
    url_input.place(x=20, y=60, width=root.winfo_width()-150, height=40)
    scarp_b.place(x=root.winfo_width()-120, y=60, width=100, height=40)
    main_frame.place(x=0, y=140, width=root.winfo_width(), height=root.winfo_height()-140)

root.bind("<Configure>", conf)
root.mainloop()

内容的提问来源于stack exchange,提问作者Hamza Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 06:15:05