我有一个tkinter应用程序,其中有2个输入框和带有数字0-9的按钮。我希望能够使用按钮输入IntVar()
,但可以将焦点输入到Entry()
中。此刻,我可以按下按钮以将IntVar()
输入到第一个Entry()
框中,但是我无法弄清楚或无法在线找到如何仅将IntVar()
输入到焦点突出的{{ 1}}框。
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
中,具体取决于哪个焦点。
答案 0 :(得分:1)
您可以将绑定添加到"<FocusIn>"
事件中,以检查焦点集中在哪个条目上,并检查insert
的值:
....
def __init__(self, *args, **kwargs):
....
self.user_number_var = IntVar()
self.pin_number_var = IntVar()
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.user_number_entry.bind("<FocusIn>", self.remember_focus)
self.pin_number_entry = Entry(self, textvariable=self.pin_number_var, 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.pin_number_entry.bind("<FocusIn>", self.remember_focus)
....
def remember_focus(self,event):
global focused_entry
focused_entry = event.widget
def press(self, num):
focused_entry.insert('end',str(num))
如果您坚持使用IntVar()
的另一种解决方案是将bind
的各个功能分别entry
,然后将global variable
设置为焦点的IntVar(),允许你然后输入你的表达到在焦点条目的IntVar()
:
...
def __init__(self, *args, **kwargs):
self.user_number_var = IntVar()
self.pin_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
)
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.user_number_entry.bind("<FocusIn>", self.set_user_number_int_var)
self.pin_number_entry = Entry(self, textvariable=self.pin_number_var, 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.pin_number_entry.bind("<FocusIn>", self.set_pin_number_int_var)
...
def set_user_number_int_var(self,event):
global set_int_var
set_int_var = self.user_number_var
def set_pin_number_int_var(self,event):
global set_int_var
set_int_var = self.pin_number_var
def press(self, num):
# point out the global expression variable
global expression,set_int_var
# concatenation of string
expression = expression + str(num)
set_int_var.set(expression)
一个缩回:串联:
expression = expression + str(num)
如果用户更改条目的焦点,并且我认为这不是期望的行为,这将继承expression
中已经存在的所有内容。
答案 1 :(得分:1)
如果我理解正确的问题,那么您真正要问的是按钮应该如何知道在何处插入文本。我认为IntVar
的使用与它无关,而是xy problem。您可以根据需要使用IntVar
,但它们与此问题无关。
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__
来解决此问题,这将迫使输入焦点从该输入小部件开始。