как получить ввод от текстового виджета tkinter, когда он находится внутри функции

относительно новичок в кодировании, и в настоящее время я играю с tkinter в python, я использую текстовый виджет внутри функции и хочу отправить ввод из текстового поля в другую функцию. Моя глобальная переменная говорит undefined на уровне модуля, поэтому как я могу определить ее на уровне модуля, если она находится внутри функции?

Когда я нажимаю кнопку отправки электронной почты, я получаю следующее сообщение об ошибке: «NameError: имя 'user_message_entry' не определено»

Какие-либо предложения? Большое спасибо!

минимальное воспроизведение:

import tkinter as tk

root = tk.Tk()
root.geometry("500x500")


def send_email():
    global user_message_entry
    subject = ":)"
    body = user_message_entry.get("1.0", "end")
    message = f"subject: {subject}\n\n {body}"
    print(message)


def feedback():
    feedback_window = tk.Toplevel()
    feedback_window.geometry("690x650")

    message_frame = tk.Frame(feedback_window)
    message_frame.grid(row=0, column=0, columnspan=3)
    user_message_entry = tk.Text(message_frame, height=10, width=60)
    user_message_entry.grid(row=0, column=0)

    send_email_button = tk.Button(feedback_window, command=send_email,
                                  height=20, width=20, bg="yellow", text="send email")
    send_email_button.grid(row=1, column=0)


open_feedback_button = tk.Button(root, command=feedback, height=20, width=20, bg="yellow", text="open feedback window")
open_feedback_button.grid(row=1, column=0)

root.mainloop()

person Kevin Nisbet    schedule 07.05.2020    source источник
comment
Вы должны переместить строку global user_message_entry в feedback().   -  person acw1668    schedule 07.05.2020
comment
@ acw1668 Это работает, но global user_message_entry по-прежнему говорит, что на уровне модуля не определено. Как я мог это отсортировать?   -  person Kevin Nisbet    schedule 07.05.2020
comment
Тогда вам лучше передать значение входа в качестве аргумента send_email().   -  person acw1668    schedule 07.05.2020
comment
Извините, вы можете подробнее рассказать об этом?   -  person Kevin Nisbet    schedule 07.05.2020
comment
Измените def send_mail() на def send_mail(entry). Тогда send_email_button = tk.Button(..., command=lambda: send_email(user_message_entry), ...).   -  person acw1668    schedule 07.05.2020
comment
Идеально! Большое спасибо   -  person Kevin Nisbet    schedule 07.05.2020


Ответы (1)


Вы можете использовать методологию объектной ориентации, чтобы сделать симплер доступа, другой вариант, вы также можете использовать globals (), чтобы сделать переменную глобальной.

В одну сторону

globals()['user_message_entry'] = tk.Text(message_frame, height=10, width=60)

.... 

и из другой функции вы можете вызвать

body = globals()['user_message_entry'].get("1.0", "end")

Второй способ

Объектно-ориентированное программирование подходит для любого типа решения проблем, поэтому вы также можете использовать класс.

import tkinter as tk

class CBased:
    def __init__(self, master, *args, **kwargs):
        super(CBased, self).__init__(*args, *kwargs)
        self.master = master
        master.geometry("500x500")

        self.open_feedback_button = tk.Button(master, command=self.feedback, height=20, width=20, bg="yellow", text="open feedback window")
        self.open_feedback_button.grid(row=1, column=0)

    def send_email(self):
        subject = ":)"
        body = self.user_message_entry.get("1.0", "end")
        message = f"subject: {subject}\n\n {body}"
        print(message)


    def feedback(self):
        self.feedback_window = tk.Toplevel()
        self.feedback_window.geometry("690x650")

        self.message_frame = tk.Frame(self.feedback_window)
        self.message_frame.grid(row=0, column=0, columnspan=3)
        self.user_message_entry = tk.Text(self.message_frame, height=10, width=60)
        self.user_message_entry.grid(row=0, column=0)

        self.send_email_button = tk.Button(self.feedback_window, command=send_email,
                                  height=20, width=20, bg="yellow", text="send email")
        self.send_email_button.grid(row=1, column=0)

def main():
    root        = Tk()
    myobj       = CBased(root)
    root.mainloop()

if __name__ == "__main__":main()

Таким образом, вы можете вызывать каждый элемент с помощью self.xyz

person Nj Nafir    schedule 07.05.2020
comment
Большое спасибо, очень полезно! Да, через некоторое время я подумал, что было бы лучше, если бы я использовал классы с самого начала, но теперь нужно так много изменить: P Кроме того, чтобы добавить в окно, я бы просто globals()['user_message_entry'].grid(row=0, column=0), это правильно? - person Kevin Nisbet; 07.05.2020
comment
Вы можете использовать, если он соответствует вашим требованиям. Удачного кодирования! - person Nj Nafir; 07.05.2020
comment
Итак, есть ли способ сократить globals () ['user_message_entry'] ... когда мы используем его в другом месте, например, полосу прокрутки? - person Kevin Nisbet; 07.05.2020
comment
Нет никакого способа, но у вас есть возможность в классе через объектно-ориентированный манер. например self.e1 = ..., и вы можете использовать self.e1 тысячу раз, означает бесконечное время - person Nj Nafir; 07.05.2020