代码之家  ›  专栏  ›  技术社区  ›  Andrew

tkinter filedialog正在窃取焦点,如果没有python 3.4.1中的“alt tab”,则不会返回焦点。

  •  1
  • Andrew  · 技术社区  · 7 年前

    这里是第一个问题,但我已经回答了一些问题,所以希望这里有足够的信息让别人给我一个指向正确方向的指针。

    我有以下代码将构成我正在构建的应用程序的一部分。我希望用户能够输入他们的名字和评估一些图像,评分他们使用的滑块。为了定义图像的来源,我想使用 filedialog.askdirectory 因此,用户可以验证包含图像的正确文件夹。

    我已经去掉了记录数据的按钮和函数,以简化这个过程。

    所以,我的问题是,当窗口弹出时,文件对话框出现,允许我选择文件夹。在我选择之后, Entry 无法选择允许用户键入其名称的字段。如果我通过alt选项卡或单击另一个窗口并返回来离开窗口,我可以定位光标并正常继续-显然,这对我的最终用户来说并不理想。

    这里显示的是文件对话框弹出窗口:

    <code>filedialog</code> popup

    第二个窗口不会自动聚焦:

    Second (main application) Window

    import tkinter as tk
    from tkinter import filedialog
    import numpy as np
    
    class Model:
    
        def __init__(self):
    
            self.scores = []
            self.position = 0
            self.first_name = ""
            self.last_name = ""
    
    
    class WelcomeWindow:
    
    
        def __init__(self, master):
    
            button_width=25
            button_height=10
            self.master = master
            self.frame = tk.Frame(self.master)
            #self.file_dialog = tk.Frame(self.master)
            self.directory = filedialog.askdirectory(parent=self.master)
            self.canvas = tk.Canvas(self.frame,
                                    height=600,
                                    width=800
                                   )
            self.model = Model()
            self.first_name_entry = tk.Entry(self.frame)
            self.last_name_entry = tk.Entry(self.frame)
    
            self.slider = tk.Scale(self.frame, 
                                   length=button_width * 20,
                                   width=button_width * 2,
                                   sliderlength=150,
                                   showvalue=False,
                                   from_=-3.00,
                                   to=3.00,
                                   orient="horizontal",
                                   tickinterval=1,
                                   label="Here is a slider",
                                   resolution=0.01
                                  )
            self.frame.pack()
            self.first_name_entry.pack()
            self.last_name_entry.pack()
            self.canvas.pack()
            self.slider.pack()
    
    def main():
        root = tk.Tk()
        win = WelcomeWindow(root)
        root.mainloop()
    
    main()
    

    我试过设置 takefocus 选项为 frame 为了 first_name_entry 字段到 True 没有成功。我也试过调整 self.directory self.frame 这完全消除了我与主窗口交互的能力。

    如果我遗漏了什么,请留下评论,我会尽我所能提供任何信息。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Mike - SMT    7 年前

    在Windows系统中有一个已知问题,在主循环第一次完全循环之前使用filedialog会导致这种焦点问题。

    最初我用 after() 安排文件对话框在第一个循环完成后某个时间发生,但要感谢 fhdrsdg's 注释有一种更简单的方法可以使用 update_idletasks() .

    这里是重新编写的代码,用于解决焦点问题和一些常规清理。

    import tkinter as tk
    from tkinter import filedialog
    
    
    class Model:
        def __init__(self):
            self.scores = []
            self.position = 0
            self.first_name = ""
            self.last_name = ""
    
    
    class WelcomeWindow(tk.Tk):
        def __init__(self):
            super().__init__()
            button_width = 25
            button_height = 10
            self.frame = tk.Frame(self)
            self.directory = ''
            self.canvas = tk.Canvas(self.frame, height=600, width=800)
            self.model = Model()
            self.first_name_entry = tk.Entry(self.frame)
            self.last_name_entry = tk.Entry(self.frame)
            self.slider = tk.Scale(self.frame, length=button_width * 20, width=button_width * 2, sliderlength=150, showvalue=False,
                                   from_=-3.00, to=3.00, orient="horizontal", tickinterval=1, label="Here is a slider", resolution=0.01)
            self.frame.pack()
            self.first_name_entry.pack()
            self.last_name_entry.pack()
            self.canvas.pack()
            self.slider.pack()
            self.update_idletasks() # adding this here fixes the focus issue
            self.directory = filedialog.askdirectory()
    
    
    def main():
        WelcomeWindow().mainloop()
    
    if __name__ == "__main__":
        main()