Tkinter: NameError: имя «root» не определено

Я разделил свое приложение tkinter на несколько файлов, и сейчас у меня есть два файла:

Main.py

import tkinter as tk

from login_info import LoginInfo 


class Main(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)        

        self.login_page = LoginInfo(self)
        self.login_page.pack(expand='True')     

if __name__ == "__main__":
    root = tk.Tk()
    Main(root).pack(side = "top", fill = "both", expand=True)
    root.mainloop()

Login_page.py

import tkinter as tk
class LoginInfo(tk.Frame):
   def __init__(self, parent, *args, **kwargs):
       tk.Frame.__init__(self, parent, *args, **kwargs)

       self.login_frame = tk.Frame(self)
       self.login_frame.pack()

       self.username_label = tk.Label(self.login_frame, text='Username:')
       self.username_label.grid(row=0, column=0, padx=(10,0), pady=(10,0))

       self.username_entry = tk.Entry(self.login_frame)
       self.username_entry.grid(row=0, column=1, padx=(10,0), pady=(10,0))

       self.password_label = tk.Label(self.login_frame, text='Password:')
       self.password_label.grid(row=1, column=0, padx=(10,0), pady=(10,0))

       self.password_entry = tk.Entry(self.login_frame)
       self.password_entry.grid(row=1, column=1, padx=(10,0), pady=(10,0))

       self.login_button = tk.Button(self.login_frame, text='Login', command=self.login)

       self.login_button.grid(row=2, column=0, columnspan=2, pady=20)
       root.bind('<Return>', self.login)

   def login(self,event):
       print('Logged In')

if __name__ == "__main__":
   root = tk.Tk()
   LoginInfo(root).pack(side = "top", fill = "both", expand=True)
   root.mainloop()

На странице входа я пытаюсь связать кнопку возврата с функцией, но получаю эту ошибку:

NameError: name 'root' is not defined

Это происходит, только если я запускаю код из main.py, если я запускаю его из login_page.py, он работает

Что ты хочешь делать на линии root.bind('<Return>', self.login)? Когда login_page.py импортируется, root не определяется в модуле.

acw1668 20.11.2022 01:35
Мутабельность и переработка объектов в Python
Мутабельность и переработка объектов в Python
Объекты являются основной конструкцией любого языка ООП, и каждый язык определяет свой собственный синтаксис для их создания, обновления и...
Другой маршрут в Flask Python
Другой маршрут в Flask Python
Flask - это фреймворк, который поддерживает веб-приложения. В этой статье я покажу, как мы можем использовать @app .route в flask, чтобы иметь другую...
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
Проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
Python PyPDF2 - запись метаданных PDF
Python PyPDF2 - запись метаданных PDF
Python скрипт, который будет записывать метаданные в PDF файл, для этого мы будем использовать PDF ридер из библиотеки PyPDF2 . PyPDF2 - это...
Переменные, типы данных и операторы в Python
Переменные, типы данных и операторы в Python
В Python переменные используются как место для хранения значений. Пример переменной формы:
Почему Python - идеальный выбор для проекта AI и ML
Почему Python - идеальный выбор для проекта AI и ML
Блог, которым поделился Harikrishna Kundariya в нашем сообществе Developer Nation Community.
0
1
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Удалите дубли...

if __name__ == "__main__":
   root = tk.Tk()
   LoginInfo(root).pack(side = "top", fill = "both", expand=True)
   root.mainloop()

... из login_page.py и запустить код из main.py.

Используйте if __name__ == '__main__':... только один раз и только в модуле, который запускает программу. Потому что только в этом модуле специальная переменная __main__ будет иметь значение '__main__'.

Кроме того, убедитесь, что вы импортируете из login_page, а не из login_info в main.py, как вы назвали этот модуль login_page.py, а не login_info.py.

Конкретный код

Я смог запустить ваш пример, выполнив следующие действия:

# main.py

import tkinter as tk

from login_page import LoginPage

class Main(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)
    self.login_page = LoginPage(self)
    self.login_page.pack(expand='True')

if __name__ == "__main__":
  root = tk.Tk()
  main = Main(root)
  main.pack(side = "top", fill = "both", expand=True)
  root.mainloop()
# login_page.py

import tkinter as tk

class LoginPage(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)
    
    self.login_frame = tk.Frame(self)
    self.login_frame.pack()
    
    self.username_label = tk.Label(self.login_frame, text='Username:')
    self.username_label.grid(row=0, column=0, padx=(10,0), pady=(10,0))
    
    self.username_entry = tk.Entry(self.login_frame)
    self.username_entry.grid(row=0, column=1, padx=(10,0), pady=(10,0))
    
    self.password_label = tk.Label(self.login_frame, text='Password:')
    self.password_label.grid(row=1, column=0, padx=(10,0), pady=(10,0))
    
    self.password_entry = tk.Entry(self.login_frame)
    self.password_entry.grid(row=1, column=1, padx=(10,0), pady=(10,0))
    
    self.login_button = tk.Button(self.login_frame, text='Login', command=self.login)
    
    self.login_button.grid(row=2, column=0, columnspan=2, pady=20)
    
    self.bind_all('<Return>', self.login)

  def login(self, event=None):
    print('Logged In')

Хитрость заключается в том, чтобы использовать self.bind_all вместо root.bind в нижней части login_page.py, что привязывает ключ ко всему приложению. Эта функция, похоже, не задокументирована в официальных документах Python tkinter , что может указывать на то, что существует более питоническое решение.

Я лично предпочел бы поместить объявление об этой привязке в файл main.py. Здесь у нас есть подчиненный модуль, который молча модифицирует родительский модуль. Чем больше становится проект, тем больше это приводит к проблемам.

Обратите внимание, что self.login() используются опцией command кнопки и bind(), поэтому аргумент event должен быть необязательным. В противном случае, когда он вызывается нажатием кнопки, будет возбуждено исключение.

acw1668 20.11.2022 02:11

Просто измените def login(self, event) на def login(self, event=None), если аргумент event не используется внутри функции.

acw1668 20.11.2022 02:18

Другие вопросы по теме