Python tkinter- объект не имеет атрибута

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

Traceback (most recent call last):
  File "C:/Users/Test_Practice.py", line 53, in <module>
middle_buttons_class().Run_Button()
  File "C:/Users/Test_Practice.py", line 14, in Run_Button
run_thread = threading.Thread(target=middle_buttons_class.Run_Robot_Files(self))
  File "C:/Users/Test_Practice.py", line 23, in Run_Robot_Files
progress_bar().done_progress.config(state=tkinter.NORMAL)
AttributeError: 'progress_bar' object has no attribute 'done_progress'

Я считаю, что это может быть забавная проблема с потоками, но я не уверен, может ли кто-нибудь меня поискать?

class MiddleButtonsClass():

    def run_button(self):
        run_thread = threading.Thread(target=middle_buttons_class.Run_Robot_Files(self))
        run_thread.daemon = True
        run_thread.start()

    def run_robot_files(self):

        print("Tasks started")
        progress_bar().progress_bar_thread()
        progress_bar().done_progress.config(state=tkinter.NORMAL)


class ProgressBar():

    def progress_bar_thread(self):
        progress_bar_class = progress_bar()
        progress_thread = threading.Thread(target=progress_bar_class.initialize_progress_bar())
        progress_thread.daemon = True
        progress_thread.start()

    def initialize_progress_bar(self):
        self.progress_window = tkinter.Toplevel()
        self.progress_window.geometry("500x250")
        self.progress_window.title("In Progress")
        self.percentage_variable = tkinter.DoubleVar()
        self.progressbar = tkinter.ttk.Progressbar(self.progress_window, style='text.Horizontal.TProgressbar',
                                   variable=self.percentage_variable, maximum=500,
                                   length=450, mode = "determinate")
        self.progressbar.pack(pady=100)
        self.done_progress = tkinter.Button(self.progress_window, text = "Done", state=tkinter.DISABLED,
                                   command=None)
        self.done_progress.pack()



if __name__ == "__main__":
    master = tkinter.Tk()
    master.title("Test Runner")
    master.geometry("750x500")
    middle_buttons_class().Run_Button()
    master.mainloop()

Привет, не могли бы вы опубликовать полную трассировку?

toti08 29.10.2018 13:04

Да, я только что добавил полную трассировку.

S.McWhorter 29.10.2018 13:08

Пожалуйста, напишите свой пример как что-то проверяемое. Нам нужно ваше корневое окно и вызов ваших классов. Пожалуйста, предоставьте Минимальный, полный и проверяемый пример.

Mike - SMT 29.10.2018 13:54

Хорошо, я обновил свой код.

S.McWhorter 29.10.2018 14:24

Не могли бы вы объяснить, почему вы используете так много потоков? Вы запускаете поток в middle_buttons_class и поток для индикатора выполнения. Может быть, вы можете добавить какое-то объяснение того, чего вы пытаетесь здесь достичь ...

toti08 29.10.2018 14:29

Проблема, которую я вижу, заключается в том, что вы создаете экземпляр progress_bar дважды подряд. В первый раз, когда вы пытаетесь выполнить поток метода внутри класса, второй раз вы пытаетесь настроить атрибут класса, который не был инициализирован. Вы неправильно понимаете, как вызвать часть класса и обновить часть класса. Вы не можете просто вспомнить класс отдельно. Вам нужно назначить класс переменной, а затем отредактировать эту переменную. Вы также создаете копию класса внутри класса.

Mike - SMT 29.10.2018 14:31
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
481
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пожалуйста, взгляните на Соглашение об именах Python, это поможет улучшить читаемость вашего кода.

Вам необходимо инициализировать новый объект:

def run_robot_files(self):

    print("Tasks started")
    progressBar = progress_bar()
    progressBar.progress_bar_thread()
    progressBar.done_progress.config(state=tkinter.NORMAL)

Вы не можете инициализировать новый экземпляр здесь:

def progress_bar_thread(self):
    progress_bar_class = progress_bar()

так что измените его на:

def progress_bar_thread(self):
    progress_bar_class = self

Спасибо за ответ, но это не сработало. Я обновил код, может это поможет.

S.McWhorter 29.10.2018 14:21

Что ж, я вижу, вы тем временем изменили свой код. Пожалуйста, обновите также Traceback

Dawid Fieluba 29.10.2018 14:24

Еще раз спасибо за ваш ответ, но, похоже, он не работает.

S.McWhorter 29.10.2018 14:36

Вам нужно переименовать переменную progress_bar , иначе вы получите ошибку UnboundLocalError: local variable 'progress_bar' referenced before assignment. Также необходимо изменить цель на себя вместо нового экземпляра. Итак, progress_bar_class = progress_bar() должен быть progress_bar_class = self.

Mike - SMT 29.10.2018 14:56
Ответ принят как подходящий

Итак, ваша проблема в том, что вы пытаетесь редактировать из двух отдельных экземпляров progress_bar(). Что вам нужно сделать, так это создать переменную для работы, а затем отредактировать атрибуты класса оттуда. Я также изменил цель вашего потока, чтобы использовать self вместо попытки создать еще один экземпляр класса.

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

Тем не менее, ваш код нуждается в некоторой доработке.

import tkinter
import threading
import tkinter.ttk as ttk

class middle_buttons_class():

    def Run_Button(self):
        run_thread = threading.Thread(target=self.Run_Robot_Files())
        run_thread.daemon = True
        run_thread.start()

    def Run_Robot_Files(self):

        print("Tasks started")
        progress_bar_var = progress_bar()
        progress_bar_var.progress_bar_thread()
        progress_bar_var.done_progress.config(state=tkinter.NORMAL)


class progress_bar():

    def progress_bar_thread(self):
        progress_bar_class = self
        progress_thread = threading.Thread(target=progress_bar_class.initialize_progress_bar())
        progress_thread.daemon = True
        progress_thread.start()

    def initialize_progress_bar(self):
        self.progress_window = tkinter.Toplevel()
        self.progress_window.geometry("500x250")
        self.progress_window.title("In Progress")
        self.percentage_variable = tkinter.DoubleVar()
        self.progressbar = tkinter.ttk.Progressbar(self.progress_window, style='text.Horizontal.TProgressbar',
                                variable=self.percentage_variable, maximum=500,length=450, mode = "determinate")
        self.progressbar.pack(pady=100)
        self.done_progress = tkinter.Button(self.progress_window, text = "Done", state=tkinter.DISABLED,command=self.update_progressbar)
        self.done_progress.pack()

    def update_progressbar(self):
        self.percentage_variable.set(self.percentage_variable.get() + 10)

if __name__ == "__main__":
    master = tkinter.Tk()
    master.title("Test Runner")
    master.geometry("750x500")
    middle_buttons_class().Run_Button()
    master.mainloop()

Вот и получилось! Спасибо

S.McWhorter 29.10.2018 14:42

@ S.McWhorter рад помочь. Есть ли причина для всех нитей? Потому что я думаю, что это можно упростить и сделать без многопоточности.

Mike - SMT 29.10.2018 14:45

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