Как вернуть значение функции, заданной как команда в tkinter

#python #python-3.x #tkinter #return-value #tkinter-entry

#python #python-3.x #tkinter #возвращаемое значение #tkinter-запись

Вопрос:

Я написал очень простой код на python tkinter , он содержит поле ввода. Я бы хотел сохранить значение, введенное пользователем, для себя, на случай, если мне понадобится использовать его позже.

Вот код:

 import tkinter as tk 
   
root=tk.Tk() 
  
root.geometry("600x400") 
   
def submit(): 
  
    name=name_entry.get() 
    return name
       
name_label = tk.Label(root, text = 'Username', 
                      font=('calibre', 
                            10, 'bold')) 
    
name_entry = tk.Entry(root, 
                      font=('calibre',10,'normal')) 
     
sub_btn=tk.Button(root,text = 'Submit', 
                  command = submit) 

name_label.grid(row=0,column=0) 
name_entry.grid(row=0,column=1)  
sub_btn.grid(row=2,column=1) 

root.mainloop() 
  

В функции submit , которую я написал return name , чтобы вернуть вставленное имя пользователя. Но как я могу получить к нему доступ за пределами функции? Я хочу сохранить значение где-нибудь, но я не знаю, как это сделать.

Я заранее ценю вашу любезную помощь

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

1. Простой способ — использовать глобальную переменную для хранения значения. Поэтому добавьте global name в начале submit() .

Ответ №1:

В большинстве случаев обратные вызовы отбрасывают возвращаемое значение (все tkinter обратные вызовы делают), если таковые имеются. Это связано с тем, что немного неудобно управлять возвращаемыми значениями с использованием шаблона observer, который чаще всего используется для обратных вызовов.

Существует два основных способа передачи значения из CB туда, где оно необходимо:

Один из них заключается в использовании container object — , который может быть простым python list или dict , или более сложным data class , доступным с помощью callback , и измененным для присвоения ему правильных значений.

вот очень простой пример использования словаря:

 import tkinter as tk 

def print_info():
    print(f'from print_info: {information_transfer}')

def submit(): 
    information_transfer['name'] = name_entry.get() 
    print(f'after input: {information_transfer}')
       
root=tk.Tk()   
root.geometry("600x400") 
   
name_label = tk.Label(root, text = 'Username', font=('calibre', 10, 'bold')) 
name_entry = tk.Entry(root, font=('calibre', 10, 'normal')) 
     
sub_btn = tk.Button(root,text='Submit', command=submit)
info_btn = tk.Button(root,text='print info', command=print_info)


name_label.grid(row=0, column=0) 
name_entry.grid(row=0, column=1)  
sub_btn.grid(row=2, column=1) 
info_btn.grid(row=3, column=1) 

information_transfer = {'name': None, 'other': None}
print(f'before input: {information_transfer}')

root.mainloop()
  

Другим является подход ООП, описанный @DavidGildour в другом ответе.

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

1. Запустив ваш код, я получаю сообщение об ошибке name is not defined

2. Да, конечно, извините — ключи dict должны быть строками; Я исправил опечатку.

3. ну, теперь я не получаю никаких ошибок, но печать information_transfer[name] показывает мне None , поэтому кажется, что у меня все еще нет доступа к пользовательскому вводу.

4. Пожалуйста, я добавил print_info функцию и кнопку, которая ее вызывает, для вашего удобства.

5. Не «большинство» раз. Обратные вызовы всегда отбрасывают возвращаемое значение.

Ответ №2:

Я бы рекомендовал использовать подход ООП, чтобы объект сохранял состояние:

 import tkinter as tk


class Program:
    def __init__(self):
        self.root = tk.Tk()
        self.name_label = tk.Label(self.root, text='Username',
                                   font=('calibre', 10, 'bold'))
        self.name_entry = tk.Entry(self.root, font=('calibre', 10, 'normal'))
        self.sub_btn = tk.Button(self.root, text='Submit', command=self.submit)
        self.submitted_var = tk.StringVar()

        self.submitted_label = tk.Label(self.root, text="Submitted name: ")
        self.submitted_entry = tk.Label(self.root, textvariable=self.submitted_var)

    def setup(self):
        self.submitted_label.grid(row=0, column=0)
        self.submitted_entry.grid(row=0, column=1)
        self.name_label.grid(row=1, column=0)
        self.name_entry.grid(row=1, column=1)
        self.sub_btn.grid(row=2, column=1)

    def submit(self):
        self.submitted_var.set(self.name_entry.get())

    def run(self):
        self.setup()
        self.root.mainloop()

if __name__ == '__main__':
    Program().run()
  

Затем вы можете использовать self.submitted_var.get() anywhere для получения последнего отправленного значения. Хотя более простым способом было бы связать a StringVar напрямую с name_entry , но тогда оно будет меняться каждый раз Entry , когда изменяется значение виджета, что делает кнопку отправки бесполезной.