Кнопки Python Tkinter numpad и несколько входов

1

В основном я пытаюсь сделать так, чтобы при изменении 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()
Теги:
tkinter

1 ответ

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_var либо entry_2_var?

Случается, что функция bind автоматически передает объект события в указанную вами функцию. В вашей лямбда-функции первым аргументом является x. Вы указали значение по умолчанию, но поскольку фактический объект передается функцией bind, x является объектом события. Итак, в def set_active_entry(self, name): name не является именем вашего виджета, а скорее объектом события. Поэтому, когда вы вызываете getattr(self, self._active_entry), self._active_entry - это объект события, и вы получаете сообщение об ошибке.

Исправить это довольно просто, просто примите аргумент в своей лямбда-функции, чтобы принять объект события, и убедитесь, что вы фактически передаете строку с именем функции 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'))

Ещё вопросы

Сообщество Overcoder
Наверх
Меню