发送电子邮件时TTK进度条被阻止

时间:2011-12-23 04:44:45

标签: python multithreading email tkinter

我正在使用tkinter在python中编写应用程序。在这个应用程序中,我试图发送一批电子邮件,我想在发送时显示进度条。我可以创建进度条并启动它,但是当发送电子邮件时,栏会停止移动(如果它是在发送电子邮件之前启动的话,我想在发送电子邮件之前启动栏,但是当我这样做的时候它就会挂起并且没有任何动作。

startProgressBar()
sendEmails()
stopProgressBar()

我已尝试将电子邮件发送到单独的帖子中,但我似乎没有任何运气。我正在使用高级线程模块。有什么建议吗?也许我没有让线程部分正确。我正在使用smtplib发送电子邮件。

3 个答案:

答案 0 :(得分:2)

这是一个老问题,但我所指的代码配方帮助了我一个类似的概念,所以我认为它应该被分享。

这类问题需要使用线程,以便我们完成更新GUI和执行实际任务(例如发送电子邮件)的工作。看看Active State的这个code recipe,我相信它正是你所寻找的线程(通过队列)线程和传递信息的例子。

我尝试突出代码配方中的重要部分。我不包括设置进度条本身,而是包括整体代码结构和获取/设置队列。

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()

答案 1 :(得分:0)

尝试这样做:

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)

这对你有用。 希望它有所帮助:)

答案 2 :(得分:0)

我已经在我的应用程序更新中重新讨论了这个问题。我已经使用Swing为UI将其转换为jython项目。

尽管如此,我认为使用观察者模式是解决我问题的最简单方法。拥有并发线程不是我的项目的要求,我只是想给出一个近似的进展视图。 Observer模式非常适合我的需求,Observer模式的Java实现特别有用。