在 Python 3.4.1 中,如果没有 "Alt-tab",Tkinter filedialog 正在窃取焦点并且不会返回它

Tkinter filedialog is stealing focus and not returning it without "Alt-tab" in Python 3.4.1

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

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

我删除了按钮和记录数据的功能以简化此操作。

所以,我遇到的问题是,当 window 弹出时,会出现文件对话框并允许我选择文件夹。不过,在我选择之后,Entry 字段无法 selected 以允许用户输入他们的名字。如果我通过 Alt-tab 或单击另一个 window 离开 window 并返回,我可以定位光标并照常进行 - 显然,这对我的最终用户来说并不理想.

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

第二个 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()

我已经尝试将 framefirst_name_entry 字段的 takefocus 选项设置为 True 但没有成功。我还尝试将 self.directory 的父级调整为 self.frame,这完全消除了我与主 window.

交互的能力

如果我遗漏了什么,请发表评论,我会尽我所能

在 Windows 系统上存在一个已知问题,即在 mainloop 第一次有机会完全循环之前使用 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()