Команды кнопки Tkinter, пока кнопка находится внутри класса

#python #tkinter

#python #tkinter

Вопрос:

Я создаю приложение с графическим интерфейсом в Tkinter и структурировал свою программу, используя ООП-подход. Я создал tk.Экземпляр Tk() и класс, который наследуется от tk.Фрейм принимает экземпляр Tk () в качестве параметра, и я создаю графический интерфейс и логику, стоящую за ним, внутри класса.

Внутри класса я создал холст, на котором я разместил несколько виджетов. Один из моих виджетов — это запись, а другой — кнопка. Команда кнопки должна быть функцией, которая принимает в качестве входного параметра текущее значение записи (используя метод Entry.get()) и что-то с этим делает, скажем, выводит это на экран.

Это некоторый код, в котором я воссоздал проблему:

 import tkinter as tk

class myClass(tk.Frame):
    def __init__(self, master):
        super(myClass, self).__init__(master)
        self.pack()
        self.Widgets()

    def getVal(self, val):
        print("The value is: ", val)

    def Widgets(self):
        canvas = tk.Canvas(self, width=500, height=500, bg='green')
        canvas.grid(row=0, column=0)
        entry = tk.Entry()
        button = tk.Button(text='pressme')
        button['command'] = lambda arg = entry.get() : self.getVal(arg)

        window = canvas.create_window(100, 100, window=entry)
        window2 = canvas.create_window(100, 200, window=button)

root = tk.Tk()
root.title("MyGUI")
classinstance = myClass(root)
root.mainloop()
  

Функция ‘getVal’ из класса должна выводить любое значение аргумента, где должно быть текущее значение из записи графического интерфейса. Проблема в том, что моя программа видит только начальное значение из этой записи (которое в данном случае является пустой строкой) и не изменяет его впоследствии, когда я обновляю графический интерфейс во время выполнения.

Теперь я предполагаю, что это связано с тем, что в программе main.py classinstance создается с некоторыми значениями по умолчанию перед тем, как приложение войдет в функцию mainloop() tkinter, и после выполнения этой функции цикла я не могу вернуться внутрь класса и изменить значения. Пожалуйста, помогите мне исправить эту проблему и объясните мне, как я мог бы сделать свое приложение таким, чтобы команда кнопки получала обновленную версию значения записи, а не первоначальную. Спасибо, что прочитали мой пост!

Комментарии:

1. Есть ли причина, по которой вы написали lambda arg = entry.get() : self.getVal(arg) вместо lambda: self.getVal(entry.get()) ? Что натолкнуло вас на мысль, что там необходим аргумент по умолчанию?

2. Я хотел сделать код более понятным: D. Я думаю, я понимаю, в чем была проблема. Лямбда-функция всегда использовала исходное значение ‘arg’. Спасибо. Как я могу принять ваше решение?

3. Вы не можете. Вы можете написать и принять свой собственный ответ, если хотите.

Ответ №1:

Как указал @Aran-Fey, лямбда-функция всегда использовала исходное значение ‘arg’ и не меняла его. Для того, чтобы это сработало, следует использовать метод entry.get(), а не аргумент по умолчанию:

 lambda: self.getVal(entry.get())
  

Ответ №2:

Ошибка была обнаружена в функции кнопки, потому что lambda arg = entry.get() импортируется arg только при создании кнопки. Затем, когда кнопка нажата, лямбда-выражение передает в функцию значение arg , полученное в начале, без его повторного импорта.

 import tkinter as tk

class myClass(tk.Frame):
    def __init__(self, master):
        super(myClass, self).__init__(master)
        self.pack()
        self.Widgets()

    def getVal(self, val):
        print("The value is: ", val)

    def Widgets(self):
        canvas = tk.Canvas(self, width=500, height=500, bg='green')
        canvas.grid(row=0, column=0)
        var = tk.StringVar()
        entry = tk.Entry(textvariable = var)
        button = tk.Button(text='pressme')
        button['command'] = lambda: self.getVal(var.get())

        window = canvas.create_window(100, 100, window=entry)
        window2 = canvas.create_window(100, 200, window=button)

root = tk.Tk()
root.title("MyGUI")
classinstance = myClass(root)
root.mainloop()