Python tk 输入框在 window 取消之前不会激活

Python tk entry box not active until window deselected

我有一个基于 Tk 的小型应用程序,它使用 window 的标准布局,在 init 中定义。对于其中一个子菜单项,我需要临时创建一个小表单,在成功提交后将其删除。我在下面的 mcve 中使用 start_make_canvas 中的代码即时执行此操作:

import random
import tkinter
from tkinter import *
from tkinter import messagebox
from PIL import ImageTk, Image

NONE=0
TAGGING=1
MAKECANVAS=4
TAGS=["some text","some more text"]
PICS=["c:/users/rob/desktop/camera.jpg","c:/users/rob/desktop/fridge.jpg"]

class Window(Frame):
    def __init__(self,master):
        Frame.__init__(self, master)             
        self.master=master
        self.mode=NONE
        self.init_window()
        self.start_tagging()
    def start_tagging(self):
        if self.photo is not None:
            self.photo.destroy()
            self.photo=None
        messagebox.showinfo("Start tagging")
        self.mode=TAGGING
        self.configure_buttons()
        self.show_pic()
    def init_window(self):
        menubar=Menu(self.master)
        menu=Menu(menubar,tearoff=0)
        menu.add_command(label="Start tagging",command=self.start_tagging)
        menu.add_command(label="Make canvas",command=self.start_make_canvas)
        menubar.add_cascade(label="Tag",menu=menu)
        self.master.config(menu=menubar)
        self.pack(fill=BOTH,expand=1) #take full space of root window
        self.photo=None
        self.tag_trk={}
        row=1
        for tag in TAGS:
            self.tag_trk[tag]=IntVar()
            Checkbutton(self,text=tag,variable=self.tag_trk[tag]).place(x=500,y=10+20*row)
            row+=1
        self.tag_count=StringVar()
        self.button1_label=StringVar()
        self.btn1=Button(self,textvariable=self.button1_label,command=self.button1_click)
        self.btn1.place(x=10,y=495)
        self.max_score=StringVar()
    def configure_buttons(self):
        if self.mode==NONE:
            self.button1_label.set("Tag")
        elif self.mode==TAGGING:
            self.button1_label.set("Next")
        elif self.mode==MAKECANVAS:
            self.button1_label.set("Make")
    def button1_click(self):
        if self.mode==TAGGING:
            self.show_pic()
        elif self.mode==MAKECANVAS:
            # do some things here
            for e in self.form: e.destroy()
            self.mode=NONE
            self.configure_buttons()
        elif self.mode==NONE:
            self.start_tagging()
    def show_pic(self):
        if self.photo is not None:
            self.photo.destroy()
        img=ImageTk.PhotoImage(Image.open(random.choice(PICS)))
        self.photo=tkinter.Label(self,image=img,borderwidth=0)
        self.photo.image=img
        self.photo.place(x=15,y=5)
    def start_make_canvas(self):
        if self.photo is not None:
            self.photo.destroy()
            self.photo=None
        self.mode=MAKECANVAS
        self.form=[]
        e=Label(self,text='Max score')
        e.place(x=80,y=200)
        self.form.append(e)
        e=Entry(self,textvariable=self.max_score,width=20)
        e.place(x=180,y=200)
        self.form.append(e)
        self.form[1].focus_set()
        self.configure_buttons()

def target_tags():
    global root
    root=tkinter.Tk()
    root.geometry("700x570")
    root.protocol("WM_DELETE_WINDOW", on_closing)
    app=Window(root)
    root.mainloop()

def on_closing():
    global root
    root.destroy()

if __name__ == "__main__":
    target_tags()

问题发生在从菜单 selecting "Make Canvas" 之后 - 表单创建工作正常,除了新创建的 Entry 元素在首次创建时未激活:我看不到插入光标,并且键入的文本不会进入条目。当我 select 一个不同的 window 和重新 select 我的应用程序 window 时,一切都很好。在为 mainloop 创建表单后,是否需要调用一种方法来识别有新的位需要处理?

注意:在创建 mcve 时,我发现 start_tagging 中的消息框是重现问题所必需的。没有它,一切都从一开始就有效。有了它,最初创建的复选框可以正常工作,但新的输入框不会(直到 window 为 unselected/reselected)。

出于某种原因,Entry 控件看起来好像还没有完全初始化:我什至无法单击控件并向其中输入内容,它没有反应。如果我按 Alt-Tab 键退出应用程序并返回,它会恢复正常。使用 focus_force() 有助于解决问题(在这种情况下它是合理的,因为它是作为对用户的肯定行为)。

这也可能是 Tk 中的错误,或者在 .place() 之后需要一些额外的步骤,place manual page "forgot" 提及。 (和ttk.Entry一样,所以不是过时代码的情况。)这个你可以问@tcl-core@lists.sourceforge.net