tkinter - 将 IntVar() 应用于重点 Entry() tkinter
问题描述
我有一个 tkinter 应用程序,它有 2 个输入框和数字为 0-9 的按钮。我希望能够IntVar()
使用按钮输入一个但进入焦点Entry()
。此刻我可以按下按钮进入IntVar()
第一个Entry()
框,但我无法弄清楚或在网上找到如何只进入IntVar()
焦点Entry()
框。
import sys
from tkinter import Tk, Text, BOTH, W, N, E, S, IntVar
from tkinter.ttk import Frame, Button, Label, Style, Entry
expression = ''
class Example(Frame):
def __init__(self, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.name = 'Application'
self.master.title(self.name)
self.pack(fill=BOTH, expand=True)
cancel_btn_style = Style()
cancel_btn_style.configure('CNL.TButton', background='red')
cancel_btn_style = Style()
cancel_btn_style.configure('LGN.TButton', background='green')
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
self.columnconfigure(3, weight=1)
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.rowconfigure(2, weight=1)
self.rowconfigure(3, weight=1)
self.rowconfigure(4, weight=1)
self.rowconfigure(5, weight=1)
self.user_number_var = IntVar()
self.main_label = Label(self, text=self.name)
self.main_label.grid(sticky=W, pady=4, padx=5)
self.entry_label = Label(self, text='User Number / PIN')
self.entry_label.grid(
row=1, column=0, columnspan=1,
rowspan=1, padx=5, sticky=E+W+S+N
)
vcmd = (self.register(self.__vcmd), '%P')
self.user_number_entry = Entry(
self, validate='key', validatecommand=vcmd,
textvariable=self.user_number_var
)
self.user_number_entry.grid(
row=1, column=1, columnspan=1,
rowspan=1, sticky=N+S+E+W, pady=4
)
self.pin_number_entry = Entry(self, validate='key', validatecommand=vcmd, show='*')
self.pin_number_entry.grid(
row=1, column=2, columnspan=1,
rowspan=1, sticky=N+S+E+W, pady=4
)
self.btn_1 = Button(self, text='1', command=lambda: self.press(1))
self.btn_1.grid(row=2, column=0, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_2 = Button(self, text='2', command=lambda: self.press(2))
self.btn_2.grid(row=2, column=1, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_3 = Button(self, text='3', command=lambda: self.press(3))
self.btn_3.grid(row=2, column=2, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_4 = Button(self, text='4', command=lambda: self.press(4))
self.btn_4.grid(row=3, column=0, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_5 = Button(self, text='5', command=lambda: self.press(5))
self.btn_5.grid(row=3, column=1, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_6 = Button(self, text='6', command=lambda: self.press(6))
self.btn_6.grid(row=3, column=2, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_7 = Button(self, text='7', command=lambda: self.press(7))
self.btn_7.grid(row=4, column=0, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_8 = Button(self, text='8', command=lambda: self.press(8))
self.btn_8.grid(row=4, column=1, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_9 = Button(self, text='9', command=lambda: self.press(9))
self.btn_9.grid(row=4, column=2, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.cancel_btn = Button(self, text='Cancel / Close', command=sys.exit, style='CNL.TButton')
self.cancel_btn.grid(row=5, column=0, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.btn_0 = Button(self, text='0', command=lambda: self.press(0))
self.btn_0.grid(row=5, column=1, columnspan=1, rowspan=1, sticky=N+S+E+W)
self.login_btn = Button(self, text='Log In', style='LGN.TButton')
self.login_btn.grid(row=5, column=2, columnspan=1, rowspan=1, sticky=N+S+E+W)
def press(self, num):
# point out the global expression variable
global expression
# concatenation of string
expression = expression + str(num)
# update the expression by using set method
self.user_number_var.set(expression)
def __vcmd(self, P, S):
print('__vcmd')
def main():
root = Tk()
root.geometry('540x640')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
我需要按钮来输入数字self.user_number_entry
或self.pin_number_entry
取决于哪个有焦点。
解决方案
如果我正确理解了这个问题,那么您真正要问的是按钮应该如何知道在哪里插入文本。我认为使用IntVar
与它没有任何关系,这是一个xy 问题。如果您愿意,您可以使用IntVar
s,但它们与此问题无关。
Tkinter 提供了一个命令来获取当前聚焦的小部件—— focus_get
. 单击按钮时,可以将文本插入到该小部件的末尾。您不需要使用IntVar
.
但是,您正在使用窃取焦点的 ttk 按钮。ttk 开发人员的一个糟糕的设计决定,但这不是重点。最简单的解决方案是跟踪哪个条目小部件最后获得焦点。然后,您可以直接在条目小部件中附加数字。
首先在每个条目小部件上添加一个绑定,以便在获得焦点时记住它自己。在创建条目之后的某个时间,以创建条目的相同方法执行此操作:
self.user_number_entry.bind("<FocusIn>", self._remember_focus)
self.pin_number_entry.bind("<FocusIn>", self._remember_focus)
接下来,我们需要定义_remember_focus
方法来记住哪个小部件最后获得了焦点:
def _remember_focus(self, event):
self._current_entry = event.widget
最后,我们需要修改press
命令以将数字直接附加到条目小部件中。在此示例中,我还将焦点重置为条目小部件。我不确定你是否想要那个。
def press(self, num):
self._current_entry.insert("end", str(num))
self._current_entry.focus_set()
注意:您的代码中还有其他错误会阻止此操作。具体来说,您的条目验证代码中有错误。这就是为什么我们要求一个 [mcve] (关注minimum),因为这让我们很难只关注所提出的问题。其他代码掩盖了这个问题。
为了让您知道此解决方案有效,一个简短的解决方法是暂时关闭您的输入验证。
此外,此解决方案假定您在单击按钮之前已单击其中一个条目。您可以通过调用您的 来解决此self.user_number_entry.focus_set()
问题__init__
,这将强制输入焦点从该条目小部件开始。
推荐阅读
- r - 搜索多列 dplyr
- javascript - 在 React JS 中隐藏特定组件的页眉和页脚
- reactjs - 使用 react-testing-library 进行 useContext 测试
- angular - 从 Angular 获取没有客户端密码、Power BI 的用户名/密码的 Azure AD 访问令牌
- php - 添加 Swagger Laravel 后无法创建新路由
- arrays - 将零移动到数组的开头
- reactjs - 如何检查用户是否使用 React 和 Embedded RuBy (erb) 登录?
- python - 如何从 Keras 加载本地图像?
- c# - Web 服务器上的 Crystal Reports 错误,但不是 localhost
- statistics - 关于流行病学计算的问题:辛普森悖论