You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter滚动Canvas布局中filedialog.askdirectory()触发程序冻结的问题求助

Tkinter滚动Canvas布局中filedialog.askdirectory()触发程序冻结的问题求助

我正在用Tkinter开发一个Python应用,主窗口里有个Canvas,里面嵌套了一个可滚动的Frame,这个滚动Frame里又放了好几个LabelFrame,每个LabelFrame里都有个“Select Path”按钮,本来应该弹出文件夹选择对话框的。

按钮绑定的函数如下:

def select_path(self):
    filedialog.askdirectory()

按钮的命令设置是对的(用的command=self.select_path,不是加括号的调用),但每次点击按钮,程序就会卡住,标题栏显示“(Not Responding)”。奇怪的是,如果换成filedialog.askopenfile()就完全正常。我试过给对话框传parent参数,也试过self.lift()、设置置顶窗口这些小技巧,但还是会冻结。

有没有人知道为什么在这个布局下askdirectory()会导致程序卡死,而askopenfile()却不会?谢谢!


补充说明

按照furas的建议,我把代码精简到只保留Canvas、Frame和路径按钮,这时候一切正常,但我的主程序还是有问题。以下是我精简后的测试代码:

import tkinter
from tkinter import ttk, VERTICAL, ALL
from tkinter import filedialog as fd

class MyApp(tkinter.Tk):
    def __init__(self):
        super().__init__()
        self.path_button = None
        self.label_frame_3 = None
        self.label_frame_2 = None
        self.label_frame_1 = None
        self.title('My application')
        self.resizable(False, False)
        self.geometry('1200x500')
        self.current_window = None
        self.scrollable_frame = None
        self.y_scrollbar = None
        self.my_canvas = None
        self.create_gui()

    def create_gui(self):
        # 滚动区域设置
        # 创建Canvas容器
        self.my_canvas = tkinter.Canvas(self)
        # 给Canvas添加垂直滚动条
        self.y_scrollbar = ttk.Scrollbar(self.my_canvas, orient=VERTICAL, command=self.my_canvas.yview)
        # 配置Canvas的滚动参数
        self.my_canvas.configure(yscrollcommand=self.y_scrollbar.set, width=500, height=500)

        def on_mousewheel(event):
            self.my_canvas.yview_scroll(int(-1*(event.delta/60)), "units")

        # 在Canvas内部创建可滚动的Frame
        self.scrollable_frame = tkinter.Frame(self.my_canvas, bg='white')
        self.my_canvas.bind("<Configure>", lambda e: self.my_canvas.configure(scrollregion=self.my_canvas.bbox(ALL)))
        self.my_canvas.bind_all("<MouseWheel>", on_mousewheel)
        self.my_canvas.create_window((0, 0), window=self.scrollable_frame, anchor='nw')

        # 放置Canvas和滚动条
        self.my_canvas.pack(side='left', fill='both', expand=True)
        self.y_scrollbar.pack(side='right', fill='y')
        # 滚动区域设置结束

        self.create_all_labels(200, 200)

    def create_all_labels(self, width, height):
        # 创建并放置LabelFrame 1
        self.label_frame_1 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 1 ", labelanchor='nw', width=width, height=height)
        self.label_frame_1.grid(column=0, row=1, padx=5, pady=5)
        self.create_frame(self.label_frame_1, "label_frame_1")

        # 创建并放置LabelFrame 2
        self.label_frame_2 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 2 ", labelanchor='nw', width=width, height=height)
        self.label_frame_2.grid(column=1, row=1, padx=5, pady=5)
        self.create_frame(self.label_frame_2, "label_frame_2")

        # 创建并放置LabelFrame 3
        self.label_frame_3 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 3 ", labelanchor='nw', width=width, height=height)
        self.label_frame_3.grid(column=2, row=1, padx=5, pady=5)
        self.create_frame(self.label_frame_3, "label_frame_3")

        # 创建并放置LabelFrame 4
        self.label_frame_4 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 4 ", labelanchor='nw', width=width, height=height)
        self.label_frame_4.grid(column=0, row=2, padx=5, pady=5)
        self.create_frame(self.label_frame_4, "label_frame_4")

        # 创建并放置LabelFrame 5
        self.label_frame_5 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 5 ", labelanchor='nw', width=width, height=height)
        self.label_frame_5.grid(column=1, row=2, padx=5, pady=5)
        self.create_frame(self.label_frame_5, "label_frame_5")

        # 创建并放置LabelFrame 6
        self.label_frame_6 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 6 ", labelanchor='nw', width=width, height=height)
        self.label_frame_6.grid(column=2, row=2, padx=5, pady=5)
        self.create_frame(self.label_frame_6, "label_frame_6")

        # 创建并放置LabelFrame 7
        self.label_frame_7 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 7 ", labelanchor='nw', width=width, height=height)
        self.label_frame_7.grid(column=0, row=3, padx=5, pady=5)
        self.create_frame(self.label_frame_7, "label_frame_7")

        # 创建并放置LabelFrame 8
        self.label_frame_8 = tkinter.LabelFrame(self.scrollable_frame, text=" LabelFrame 8 ", labelanchor='nw', width=width, height=height)
        self.label_frame_8.grid(column=1, row=3, padx=5, pady=5)
        self.create_frame(self.label_frame_8, "label_frame_8")

    def create_frame(self, parent, frame_name):
        # 补全按钮创建逻辑,原精简代码遗漏了这部分
        self.path_button = ttk.Button(parent, text="Select Path", command=self.select_path)
        self.path_button.pack(pady=10)

    def select_path(self):
        # 问题出在这里的askdirectory
        fd.askdirectory()
        # 如果换成下面这行就正常
        # fd.askopenfile()

if __name__ == "__main__":
    app = MyApp()
    app.mainloop()

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:19:32