TTK progress bar blocked when sending email
Asked Answered
D

3

2

I am writing an app in python using tkinter. In this app I am trying to send out a batch of emails and I want to show a progress bar while they are being sent. I am able to create the progress bar and start it, but when the emails are being sent, the bar just stops moving (If it is started way before the emails are sent, I want to start the bar just before the emails are sent, but it just hangs and nothing moves on the bar when I do it like this.

startProgressBar()
sendEmails()
stopProgressBar()

I have tried putting the sending of emails into a separate thread, but I don't seem to be having any luck. I am using the high-level Threading module. Are there any suggestions on what to do? Perhaps I am not getting the threading part correct. I am using the smtplib to send emails.

Doralynn answered 23/12, 2011 at 4:44 Comment(0)
C
2

This is an old question but the code recipe I'm referring to has helped me with a similar concept, so I thought it should be shared.

This type of problem needs to use threading so that we spilt up the job of updating the GUI and doing the actual task (such as sending emails). Have a look at this code recipe from Active State, I believe it's exactly what you're looking for as an example of threading and passing information between threads (via a queue).

I try to highlight the important parts from the code recipe. I don't include setting up the progress bar itself but rather the overall code structure and getting/setting a queue.

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()
Cachou answered 9/3, 2012 at 4:58 Comment(0)
A
0

Try doing it like this:

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)

That should work for you. Hope it helps :)

Analgesic answered 24/12, 2011 at 0:48 Comment(1)
I tried it with my code and I'm still having the same problems. I think that the problem is that when the emails are being sent the entire process "pauses". Perhaps I need to find a better way to do the sending part.Doralynn
D
0

I have since revisited this problem in an update to my application. I have converted this to a jython project using Swing for the UI.

None the less, I figured that using the observer pattern was the simplest solution to my problem. Having concurrent threads was not a requirement for my project and I simply wanted to give an approximate view of the progress. The Observer pattern suited my needs just fine, and the Java implementation of the Observer pattern was especially helpful.

Doralynn answered 3/7, 2012 at 0:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.