【问题标题】:TTK progress bar blocked when sending email发送电子邮件时 TTK 进度条被阻止
【发布时间】:2012-01-26 14:14:30
【问题描述】:

我正在使用 tkinter 在 python 中编写一个应用程序。在这个应用程序中,我正在尝试发送一批电子邮件,并且我想在发送它们时显示一个进度条。我能够创建进度条并启动它,但是当发送电子邮件时,进度条停止移动(如果它在发送电子邮件之前启动,我想在发送电子邮件之前启动进度条,但是当我这样做时,它只是挂起,没有任何东西在栏上移动。

startProgressBar()
sendEmails()
stopProgressBar()

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

【问题讨论】:

    标签: python multithreading email tkinter


    【解决方案1】:

    尝试这样做:

    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】:

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

    这种类型的问题需要使用线程,因此我们将更新 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()
    

    【讨论】:

      【解决方案3】:

      此后,我在更新我的应用程序时重新审视了这个问题。我已将其转换为使用 Swing 作为 UI 的 jython 项目。

      不过,我认为使用观察者模式是解决我的问题的最简单方法。我的项目不需要并发线程,我只是想大致了解一下进度。观察者模式非常适合我的需要,观察者模式的 Java 实现特别有用。

      【讨论】:

        猜你喜欢
        • 2019-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-02
        • 1970-01-01
        • 2016-04-06
        • 2015-04-01
        • 2012-08-12
        相关资源
        最近更新 更多