Как сделать кнопку в моем пользовательском интерфейсе tk, которая заставляет программу делать целую кучу вещей, когда она нажата, не останавливая окно? - PullRequest
0 голосов
/ 16 июля 2011

Я только начинаю работать с Tk и использую его в python.Я установил кнопку, которая делает тонну (примерно две минуты) за кулисами, когда вы нажимаете на нее.Я также настроил текст статуса, чтобы показать, что происходит, когда это происходит.Я настроил это так:

status_text = Tkinter.StringVar()
ttk.Button(mainframe, text="Stats!", command=go).grid(column=1, row=4)

def go(*args):
    status_text.set("Logging in...")
    do_lots_of_stuff()
    status_text.set("Doing stuff #1...")
    do_even_more_stuff()
    status_text.set("Success!")

Проблема в том, что когда вы нажимаете эту кнопку, окно зависает, и текст статуса никогда не меняется.Он выглядит неработающим и не выходит из этого состояния, пока вся обработка не завершится через 2-3 минуты.Как сделать так, чтобы он не зависал и обновлялся текст статуса?

Ответы [ 2 ]

1 голос
/ 16 июля 2011

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

Например, если вы do_lots_of_stuff считывает строки из файла, создайте метод, который читает одну строку, а затем помещает задание в очередь событий для вызова себя через мс или две.Таким образом, цикл событий продолжает выполняться, и ваш код выполняет небольшую обработку на каждой итерации.Это удивительно эффективный метод, хотя он работает, только если вы можете разбить «множество вещей» на атомарные куски.

Если вы не можете этого сделать, вам придется использовать несколько потоковили несколько процессов.Я лично предпочитаю последнее - многопроцессорный код (возможно) менее труден для написания и отладки.

1 голос
/ 16 июля 2011

Пришло время изучать многопоточность!

Происходит то, что графический интерфейс пользователя (основной поток) ожидает возврата метода, чтобы продолжить обновление интерфейса.

Вы будетехотите, чтобы действие кнопки вызывало threading.Thread вместо запуска тяжелого кода в основном потоке.Вы также захотите создать очередь для доступа к данным из другого потока (поскольку отправка запросов GUI должна выполняться ТОЛЬКО из основного потока).

import threading, Queue #queue in 3.x

my_queue = Queue.Queue()

def go(*args):
    my_thread = threading.Thread(target=function_that_does_stuff)

def function_that_does_stuff():
    my_queue.put("Logging in...")
    do_lots_of_stuff()
    my_queue.put("Doing stuff #1...")
    do_even_more_stuff()
    my_queue.put("Success!")

Тогда вам понадобится функция, котораязапускается, когда происходит событие обновления.

def OnUpdate(*args):
    try:
        status_text.set(my_queue.get())
    except Queue.Empty:
        pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...