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
我有一个基于 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