Tkinter:提高框架时的焦点问题
Tkinter: Focus issue when raising frame
以下代码是触摸屏的GUI(没有鼠标,没有键盘)。
输入是触摸屏,它的响应类似于鼠标点击。这是
从一个更大的程序中剥离出来以显示问题。它有3个框架
根据需要提出。理想情况下,我希望焦点无处可去
直到用户点击(指向)一个字段,然后键盘输入数字
在框架 Machine 1 或 Machine 2 的聚焦区域中。效果很好,
但如果用户没有在输入字段中首先 "click",则会生成
异常:AttributeError: 'machine1' 对象没有属性 'insert'.
如果键盘输入为 "bit bucket" 或
一个不可见(且未使用)的虚拟输入字段,但可以接受
默认情况下,当一个框架被抬起时,焦点会自动放在
第一个字段。
经过数小时的网络研究,我一直无法找到
解决方案。感谢您为我指明正确的方向。
import tkinter as tk
from tkinter import font as tkfont
class MyApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we stack the frames
# then the one we want visible is raised above the others
container = tk.Frame(self)
container.grid(row=0, column=0, sticky='news')
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frames["machine1"] = machine1(parent=container, controller=self)
self.frames["machine2"] = machine2(parent=container, controller=self)
self.frames["running"] = running(parent=container, controller=self)
self.frames["machine1"].grid(row=0, column=0, sticky="nsew")
self.frames["machine2"].grid(row=0, column=0, sticky="nsew")
self.frames["running"].grid(row=0, column=0, sticky="nsew")
self.show_frame("running")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
frame.focus_set() # this removed focus from the hidden window
class Keypad(tk.Frame):
cells = [
['1', '2', '3', '4', '5'],
['6', '7', '8', '9', '0'],
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for y, row in enumerate(self.cells):
for x, item in enumerate(row):
b = tk.Button(self, text=item, command=lambda text=item:self.append(text))
b.grid(row=y, column=x, sticky='news')
x = tk.Button(self, text='Backspace', command=self.backspace)
x.grid(row=0, column=10, sticky='news')
x = tk.Button(self, text='Clear', command=self.clear)
x.grid(row=1, column=10, sticky='news')
def get(self):
widget = self.focus_get()
return widget.get()
def append(self, text):
# get the widget with the focus
widget = self.focus_get()
# insert the value
widget.insert("insert", text)
def clear(self):
widget = self.focus_get()
widget.delete(0, 'end')
def backspace(self):
widget = self.focus_get()
text = widget.get()
text = text[:-1]
self.clear()
self.append(text)
class machine1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Machine 1", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=2, column=0, sticky='news')
e1.focus_set() # by default start with this one
e2 = tk.Entry(self, highlightthickness = 2)
e2.grid(row=3, column=0, sticky='news')
kbd = Keypad(self)
kbd.grid(row=5, column=0, columnspan=3)
button3 = tk.Button(self, text="Run",
command=lambda: controller.show_frame("running"))
button3.grid(row=6, column=2, sticky='news')
class machine2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Machine 2", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=2, column=0, sticky='news')
e1.focus_set() # by default start with this one
e2 = tk.Entry(self, highlightthickness = 2)
e2.grid(row=3, column=0, sticky='news')
kbd = Keypad(self)
kbd.grid(row=5, column=0, columnspan=3)
button3 = tk.Button(self, text="Run",
command=lambda: controller.show_frame("running"))
button3.grid(row=6, column=2, sticky='news')
class running(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Run", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
button1 = tk.Button(self, text="Machine 1",
command=lambda: controller.show_frame("machine1"))
button2 = tk.Button(self, text="Machine 2",
command=lambda: controller.show_frame("machine2"))
button1.grid(row=5, column=0, sticky='news')
button2.grid(row=5, column=1, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=1, column=1, sticky='news')
if __name__ == "__main__":
app = MyApp()
app.geometry("800x480")
app.mainloop()
``b
有些东西总是有焦点,即使它只是根 window。
对于您的情况,最简单的解决方案是验证焦点是否位于条目小部件上,您可以这样做:
def append(self, text):
widget = self.focus_get()
if widget.winfo_class() == "Entry":
widget.insert("insert", text)
以下代码是触摸屏的GUI(没有鼠标,没有键盘)。 输入是触摸屏,它的响应类似于鼠标点击。这是 从一个更大的程序中剥离出来以显示问题。它有3个框架 根据需要提出。理想情况下,我希望焦点无处可去 直到用户点击(指向)一个字段,然后键盘输入数字 在框架 Machine 1 或 Machine 2 的聚焦区域中。效果很好, 但如果用户没有在输入字段中首先 "click",则会生成 异常:AttributeError: 'machine1' 对象没有属性 'insert'.
如果键盘输入为 "bit bucket" 或 一个不可见(且未使用)的虚拟输入字段,但可以接受 默认情况下,当一个框架被抬起时,焦点会自动放在 第一个字段。
经过数小时的网络研究,我一直无法找到 解决方案。感谢您为我指明正确的方向。
import tkinter as tk
from tkinter import font as tkfont
class MyApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we stack the frames
# then the one we want visible is raised above the others
container = tk.Frame(self)
container.grid(row=0, column=0, sticky='news')
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frames["machine1"] = machine1(parent=container, controller=self)
self.frames["machine2"] = machine2(parent=container, controller=self)
self.frames["running"] = running(parent=container, controller=self)
self.frames["machine1"].grid(row=0, column=0, sticky="nsew")
self.frames["machine2"].grid(row=0, column=0, sticky="nsew")
self.frames["running"].grid(row=0, column=0, sticky="nsew")
self.show_frame("running")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
frame.focus_set() # this removed focus from the hidden window
class Keypad(tk.Frame):
cells = [
['1', '2', '3', '4', '5'],
['6', '7', '8', '9', '0'],
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for y, row in enumerate(self.cells):
for x, item in enumerate(row):
b = tk.Button(self, text=item, command=lambda text=item:self.append(text))
b.grid(row=y, column=x, sticky='news')
x = tk.Button(self, text='Backspace', command=self.backspace)
x.grid(row=0, column=10, sticky='news')
x = tk.Button(self, text='Clear', command=self.clear)
x.grid(row=1, column=10, sticky='news')
def get(self):
widget = self.focus_get()
return widget.get()
def append(self, text):
# get the widget with the focus
widget = self.focus_get()
# insert the value
widget.insert("insert", text)
def clear(self):
widget = self.focus_get()
widget.delete(0, 'end')
def backspace(self):
widget = self.focus_get()
text = widget.get()
text = text[:-1]
self.clear()
self.append(text)
class machine1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Machine 1", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=2, column=0, sticky='news')
e1.focus_set() # by default start with this one
e2 = tk.Entry(self, highlightthickness = 2)
e2.grid(row=3, column=0, sticky='news')
kbd = Keypad(self)
kbd.grid(row=5, column=0, columnspan=3)
button3 = tk.Button(self, text="Run",
command=lambda: controller.show_frame("running"))
button3.grid(row=6, column=2, sticky='news')
class machine2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Machine 2", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=2, column=0, sticky='news')
e1.focus_set() # by default start with this one
e2 = tk.Entry(self, highlightthickness = 2)
e2.grid(row=3, column=0, sticky='news')
kbd = Keypad(self)
kbd.grid(row=5, column=0, columnspan=3)
button3 = tk.Button(self, text="Run",
command=lambda: controller.show_frame("running"))
button3.grid(row=6, column=2, sticky='news')
class running(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Run", font=controller.title_font)
label.grid(row=0, column=0, sticky='news')
button1 = tk.Button(self, text="Machine 1",
command=lambda: controller.show_frame("machine1"))
button2 = tk.Button(self, text="Machine 2",
command=lambda: controller.show_frame("machine2"))
button1.grid(row=5, column=0, sticky='news')
button2.grid(row=5, column=1, sticky='news')
e1 = tk.Entry(self, highlightthickness = 2)
e1.grid(row=1, column=1, sticky='news')
if __name__ == "__main__":
app = MyApp()
app.geometry("800x480")
app.mainloop()
``b
有些东西总是有焦点,即使它只是根 window。
对于您的情况,最简单的解决方案是验证焦点是否位于条目小部件上,您可以这样做:
def append(self, text):
widget = self.focus_get()
if widget.winfo_class() == "Entry":
widget.insert("insert", text)