Можно ли получить доступ к переменной из __init__ класса с помощью функции из того же класса?

#python #tkinter #jupyter

#python #tkinter #jupyter

Вопрос:

Я хочу изменить текст в окне состояния, когда пользователь нажимает кнопку. Текущее состояние при запуске страницы — «файл не загружен», после нажатия кнопки я бы хотел, чтобы текст на этой кнопке изменился, чтобы показать, что «файл загружен» или что-то подобное.

 class PageOne(tk.Frame):
       
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Load Data from Files", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        invButton = tk.Button(self, text="Load Inventory Data", command = self.openFile)
        invButton.pack()
        invStatusText = tk.StringVar()
        invStatusText.set("No file selected") 
        invStatus = tk.Button(self, state='disabled')
        invStatus.config(textvariable=invStatusText)
        invStatus.pack()
      
    def openFile(self):
        name = fd.askopenfilename()
        self.invStatusText.set("File Loaded")
 

Когда я запустил это, не передавая self в OpenFile(), и он срабатывает при вводе функции OpenFile с сообщением NameError: name 'invStatusText' is not defined . Я стал ближе при использовании self (приведенный выше код). В этом случае я получаю следующее:

 Exception in Tkinter callback
Traceback (most recent call last):
  File "C:anaconda3libtkinter__init__.py", line 1883, in __call__
    return self.func(*args)
  File "<ipython-input-6-99355e7afb55>", line 84, in openFile1
    self.invStatusText.set("File Loaded")
AttributeError: 'PageOne' object has no attribute 'invStatusText'
 

Итак, я хотел бы изменить текст кнопки invButton, изменив значение переменной, хранящейся в __init__ функции, но это мне не позволяет. Я видел в другом месте (у меня открыто около 20 вкладок StackOverflow), что эти переменные должны быть определены на уровне класса, за пределами __init__ , но когда я попытался поместить invStatusText внутри класса, я получил сообщение AttributeError: 'NoneType' object has no attribute '_root'

Ответ №1:

В __init__ вам нужно сделать атрибут, который вы хотите вызвать, атрибутом экземпляра (добавив к нему self):

 class PageOne(tk.Frame):
       
    def __init__(self, parent, controller):
        ...
        self.invStatusText.set("No file selected") 
        ...
      
    def openFile(self):
        name = fd.askopenfilename()
        self.invStatusText.set("File Loaded")

 

Также я хотел бы отметить, что обычно вы не должны что-то делать __init__ . Создайте отдельный метод для создания пользовательского интерфейса, а не делайте это там. По мере роста вашего пользовательского __init__ интерфейса ваш станет непонятным.

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

1. Спасибо, это было все, и я буду использовать совет о создании метода createUI для выполнения всего этого типа вещей, очень признателен.