Python Tkinter小键盘按钮和多个输入

时间:2018-06-18 15:11:46

标签: python tkinter

基本上我尝试这样做,以便当您更改Entry输入字段时,该按钮会将其标签附加到正确的输入。

我使用active_entry来定位刚关注的输入。由于某种原因,事件绑定没有正确地将其更改为新的输入字段。

更改默认Entry然后按button_1后的实际结果:TypeError: getattr(): attribute name must be string

from tkinter import *

class App(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.set_active_entry('entry_1_var')  # set initial active entry
        self.entry_1_var = StringVar()
        self.entry_2_var = StringVar()
        self.entry_1 = Entry(self, width=10, font='Helvetica 32', textvariable=self.entry_1_var)
        self.entry_2 = Entry(self, width=10, font='Helvetica 32', textvariable=self.entry_2_var)
        self.create_widgets()
        self.entry_binding()

    def set_active_entry(self, name):
        self._active_entry = name
        print(self._active_entry)

    @property
    def active_entry(self):
        return getattr(self, self._active_entry)

    @active_entry.setter
    def active_entry(self, value):
        setattr(self, self._active_entry, value)

    def create_widgets(self):
        self.entry_1.pack()
        self.entry_2.pack()

        label = '1'
        button_1 = Button(self, text=label, width=10, height=5, command=lambda x=label: self.num_pad(x))
        button_1.pack()

    def entry_binding(self):
        self.entry_1.bind('<FocusIn>', lambda x='entry_1_var': self.set_active_entry(x))
        self.entry_2.bind('<FocusIn>', lambda x='entry_2_var': self.set_active_entry(x))

    def num_pad(self, label):
        current_text = self.active_entry.get()
        self.active_entry.set(current_text+label)

app = App()
app.mainloop()

1 个答案:

答案 0 :(得分:1)

问题出在这些方面

self.entry_1.bind('<FocusIn>', lambda x='entry_1_var': self.set_active_entry(x))
self.entry_2.bind('<FocusIn>', lambda x='entry_2_var': self.set_active_entry(x))

当您点击其中一个条目时,您会看到<FocusIn event>正在打印,相反,您可能会认为它是entry_1_varentry_2_var吗?

bind函数自动将事件对象传递给您指定的函数时,会发生什么。在lambda函数中,第一个参数是x。您确实指定了默认值,但由于bind函数传递了实际对象,因此x是事件对象。因此,在def set_active_entry(self, name):中,name不是您的小部件的名称,而是事件对象。因此,当您致电getattr(self, self._active_entry)时,self._active_entry是事件对象,您会收到错误。

对此的修复实际上非常简单,只需在lambda函数中接受一个参数来接受事件对象,并确保实际将带有名称的字符串传递给set_active_entry函数:

self.entry_1.bind('<FocusIn>', lambda e, x='entry_1_var': self.set_active_entry(x))
self.entry_2.bind('<FocusIn>', lambda e, x='entry_2_var': self.set_active_entry(x))

self.entry_1.bind('<FocusIn>', lambda e: self.set_active_entry('entry_1_var'))
self.entry_2.bind('<FocusIn>', lambda e: self.set_active_entry('entry_2_var'))