Индикатор выполнения TTK заблокирован при отправке электронной почты - PullRequest
2 голосов
/ 23 декабря 2011

Я пишу приложение на python, используя tkinter. В этом приложении я пытаюсь отправить партию писем и хочу показать индикатор выполнения, пока они отправляются. Я могу создать индикатор выполнения и запустить его, но когда электронные письма отправляются, панель просто перестает двигаться (если она запущена задолго до отправки электронных писем, я хочу запустить панель непосредственно перед отправкой электронных писем, но он просто зависает, и ничто не движется на панели, когда я делаю это так.

startProgressBar()
sendEmails()
stopProgressBar()

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

Ответы [ 3 ]

2 голосов
/ 09 марта 2012

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

В этом типе проблемы необходимо использовать многопоточность, чтобы мы ускорили работу по обновлению графического интерфейса и выполнению реальной задачи (например, отправка электронных писем). Взгляните на этот кодовый рецепт из Active State, я считаю, что это именно то, что вы ищете в качестве примера потоков и передачи информации между потоками (через очередь).

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

import Tkinter
import threading
import Queue

class GuiPart:
    def __init__(self, master, queue, endCommand):
        self.queue = queue
        # Do GUI set up here (i.e. draw progress bar)

        # This guy handles the queue contents
        def  processIncoming(self):
            while self.queue.qsize():
                try:
                    # Get a value (email progress) from the queue 
                    progress = self.queue.get(0)
                    # Update the progress bar here.

                except Queue.Empty:
                    pass

class ThreadedClient:
    # Launches the Gui and does the sending email task
    def __init__(self, master):
        self.master = master
        self.queue = Queue.Queue()

        # Set up the Gui, refer to code recipe
        self.gui = GuiPart(master, self.queue, ...)

        # Set up asynch thread (set flag to tell us we're running)
        self.running = 1        
        self.email_thread = threading.Thread(target = self.send_emails)
        self.email_thread.start()

        # Start checking the queue
        self.periodicCall()

     def periodicCall(self):
         # Checks contents of queue
         self.gui.processIncoming()
         # Wait X milliseconds, call this again... (see code recipe)

     def send_emails(self): # AKA "worker thread"
         while (self.running):
             # Send an email
             # Calculate the %age of email progress

             # Put this value in the queue!
             self.queue.put(value)

     # Eventually run out of emails to send.
     def endApplication(self):
         self.running = 0


root = Tkinter.Tk()
client = ThreadedClient(root)
root.mainloop()
0 голосов
/ 03 июля 2012

С тех пор я повторно рассмотрел эту проблему в обновлении моего приложения.Я преобразовал это в проект jython, используя Swing для пользовательского интерфейса.

Тем не менее, я решил, что использование шаблона наблюдателя было самым простым решением моей проблемы.Наличие параллельных потоков не было требованием для моего проекта, и я просто хотел дать приблизительное представление о прогрессе.Шаблон Observer вполне соответствовал моим потребностям, и реализация шаблона Observer на Java была особенно полезна.

0 голосов
/ 24 декабря 2011

Попробуйте сделать это так:

progress = ttk.Progressbar(bottommenuframe, orient=HORIZONTAL, length=100, maximum=(NUMBEROFEMAILS), mode='determinate')
progress.pack(side=RIGHT)

def emailing():
    progress.start()   
    ##send 1 email
    progress.step(1)

    if all emails sent:
        progress.stop()

    root.after(0, emailing)

Это должно сработать для вас. Надеюсь, это поможет:)

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