将IntVar()应用于焦点条目()tkinter

将IntVar()应用于焦点条目()tkinter,tkinter,python-2.x,Tkinter,Python 2.x,我有一个tkinter应用程序,它有两个输入框和数字为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,

我有一个tkinter应用程序,它有两个输入框和数字为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\u number\u条目
self.pin\u number\u条目
中输入数字,具体取决于哪个条目有焦点

您可以向
事件添加一个绑定,以检查哪个条目是焦点,并插入您的值:

....

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))
一个缩回:连接:

 expression = expression + str(num)

如果用户更改条目的焦点,这将继承
表达式中已经存在的任何内容,我猜这不是一个期望的行为。

您可以向
事件添加绑定,以检查哪个条目是焦点,并插入您的值:

....

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))
一个缩回:连接:

 expression = expression + str(num)

如果用户更改了输入的焦点,这将继承
表达式中已有的内容,我想这不是一个期望的行为。

如果我理解正确的问题,那么您真正要问的是按钮应该如何知道插入文本的位置。我不认为使用
IntVar
与此有任何关系,这是一个错误。如果愿意,可以使用
IntVar
s,但它们与此问题无关

Tkinter提供一个命令来获取当前关注的小部件--
focus\u get
。单击按钮时,可以将文本插入该小部件的末尾。您不需要使用
IntVar

但是,您使用的ttk按钮窃取了焦点。ttk开发人员做出了一个糟糕的设计决策,但这与问题无关。最简单的解决方案是跟踪哪个条目小部件最后有焦点。然后,您可以直接在entry小部件中追加数字

首先在每个条目小部件上添加一个绑定,以便在它获得焦点时记住自己。在创建条目后的某个时间,使用创建条目的相同方法执行此操作:

self.user_number_entry.bind("<FocusIn>", self._remember_focus)
self.pin_number_entry.bind("<FocusIn>", self._remember_focus)
最后,我们需要修改
press
命令,将数字直接附加到entry小部件中。在本例中,我还将焦点重置为entry小部件。我不确定你是否想要

def press(self, num):
    self._current_entry.insert("end", str(num))
    self._current_entry.focus_set()

注意:您的代码中还有其他错误,这些错误将阻止此操作。具体来说,您的条目验证代码中有bug。这就是为什么我们要求[mcve](关注最小值),因为这使得我们很难只关注被问的问题。另一个代码掩盖了这个问题

为了让您知道此解决方案正在工作,一个简短的修复方法是暂时关闭输入验证


此外,此解决方案假定您在单击按钮之前已单击其中一个条目。您可以通过调用
中的
self.user\u number\u entry.focus\u set()
来解决这个问题,这将强制输入焦点从该条目小部件开始。

如果我理解正确的问题,那么您真正要问的是按钮应该如何知道插入文本的位置。我不认为使用
IntVar
与此有任何关系,这是一个错误。如果愿意,可以使用
IntVar
s,但它们与此问题无关

Tkinter提供一个命令来获取当前关注的小部件--
focus\u get
。单击按钮时,可以将文本插入该小部件的末尾。您不需要使用
IntVar

但是,您使用的ttk按钮窃取了焦点。ttk开发人员做出了一个糟糕的设计决策,但这与问题无关。最简单的解决方案是跟踪哪个条目小部件最后有焦点。然后,您可以直接在entry小部件中追加数字

首先在每个条目小部件上添加一个绑定,以便在它获得焦点时记住自己。在创建条目后的某个时间,使用创建条目的相同方法执行此操作:

self.user_number_entry.bind("<FocusIn>", self._remember_focus)
self.pin_number_entry.bind("<FocusIn>", self._remember_focus)
最后,我们需要修改
press
命令,将数字直接附加到entry小部件中。在本例中,我还将焦点重置为entry小部件。我不确定你是否想要

def press(self, num):
    self._current_entry.insert("end", str(num))
    self._current_entry.focus_set()

注意:您的代码中还有其他错误,这些错误将阻止此操作。具体来说,您的条目验证代码中有bug。这就是为什么我们要求[mcve](关注最小值),因为这使得我们很难只关注被问的问题。另一个代码掩盖了这个问题

为了让您知道此解决方案正在工作,一个简短的修复方法是暂时关闭输入验证


此外,此解决方案假定您在单击按钮之前已单击其中一个条目。您可以通过在
\uuu init\uuuu
中调用
self.user\u number\u entry.focus\u set()
来解决这个问题,这将强制输入焦点从该条目小部件开始。

我在玩bind函数,但无法使其按预期工作,因此认为这可能是错误的方法。我一到电脑前就会测试你的例子。非常感谢。@BryanOakley,与其说人们错了,为什么不提供一些帮助呢?你花了很多时间来评论我错了,查克G错了,但你并没有说任何有帮助的话!如何“要求它提供当前有焦点的小部件”?在我尝试的几个变体中,我尝试了类似的方法,
get\u focus()
set\u focus()
不起作用,我看到你在tkinter上回答了很多问题,所以你肯定能帮上忙,但你没有提供任何有用的东西,我建议你加入我的道歉。我不认识你