Как запустить tkinter после события вместе с другой задачей? - PullRequest
0 голосов
/ 07 июня 2019

Я пытаюсь создать графический интерфейс tkinter для скрипта, который выполняет какую-то задачу.Задача запускается нажатием кнопки «Пуск», и я хотел бы добавить динамическую метку, показывающую, что задача «выполняется», с отображением: «Работает».→ «Working ..» → «Working ...»

Я сослался на этот пост и написал следующий скрипт.Здесь я использовал индикатор выполнения, чтобы представить свою «задачу», и ожидал, что метка состояния изменится (как указано выше), пока индикатор выполнения обновляется.

import tkinter as tk

class UI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('Hello World')

        self.prog_Label = tk.Label(self.root, text='Progress')
        self.prog_Label.grid(row=0, column=0, sticky=tk.W, padx=20, pady=(10, 0))

        self.prog_Bar = tk.ttk.Progressbar(self.root)
        self.prog_Bar.configure(value=0, mode='determinate', orient='horizontal')

        self.prog_Bar.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20, pady=5)

        self.exe_Btn = tk.Button(self.root, text='Start', padx=15, command=self.run, relief='groove')
        self.exe_Btn.grid(row=2, column=0, padx=80, pady=(40, 20), sticky=tk.E)

        self.prog_Label = tk.Label(self.root, text='Status:-')
        self.prog_Label.grid(row=3, column=0, sticky=tk.W, padx=20, pady=10)

        self.root.mainloop()

    def run(self):
        self.update_status('Working')
        n = 0
        self.prog_Bar.configure(value=n, maximum=100000, mode='determinate', orient='horizontal')
        for i in range(100000):
            n += 1
            self.prog_Bar.configure(value=n)
            self.prog_Bar.update_idletasks()

    def update_status(self, status=None):
        if status is not None:
            current_status = 'Status: ' + status
        else:
            current_status = self.prog_Label['text']
            if current_status.endswith('...'):
                current_status = current_status.replace('...', '')
            else:
                current_status += '.'

        self.prog_Label['text'] = current_status
        self.prog_Label.update_idletasks()
        self._status = self.root.after(1000, self.update_status)

if __name__ == '__main__':
    ui = UI()

Однако программа ведет себя таким образомчто, когда нажимается кнопка «Пуск», хотя метка состояния немедленно меняется с «-» на «Рабочая», она начинает добавлять точки только после того, как индикатор выполнения достигает конца.

Есть ли способ изменить его, чтобы достичь моей цели?

1 Ответ

1 голос
/ 07 июня 2019

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

import threading
import time

import tkinter as tk
import tkinter.ttk as ttk

class Task:
    def __init__(self):
        self.percent_done = 0

        threading.Thread(target = self.run).start()

    def run(self):
        while self.percent_done < 1:
            self.percent_done += 0.1

            # Do your task here

            time.sleep(0.5)

        self.percent_done = 1


class Application():
    def __init__(self):
        self.root = tk.Tk()

        self.root.title("Window Title")

        self.task = None
        self.label_dots = 0

        self.prog_bar = tk.ttk.Progressbar(self.root)
        self.prog_bar.configure(value=0, maximum=100, mode='determinate', orient='horizontal')

        self.prog_bar.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20, pady=5)

        self.run_btn = tk.Button(self.root, text='Start', padx=15, command=self.start_task, relief='groove')
        self.run_btn.grid(row=2, column=0, padx=80, pady=(40, 20), sticky=tk.E)

        self.prog_label = tk.Label(self.root, text='Status: -')
        self.prog_label.grid(row=3, column=0, sticky=tk.W, padx=20, pady=10)

    def start_task(self):       
        self.task = Task()

        self.update_ui()


    def update_ui(self):
        # Percent is between 0 and 1 
        if 0 < self.task.percent_done < 1:
            status = "Working"

            self.label_dots += 1
            self.label_dots = self.label_dots % 4
        else:
            status = "Finished"

            self.label_dots = 0

        self.prog_bar.configure(value=self.task.percent_done * 100)

        label_text = "Status: - " + status + ("." * self.label_dots)

        self.prog_label.config(text = label_text)

        if status != "Finished":
            self.root.after(1000, self.update_ui)           


Application().root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...