2011-12-23 28 views
2

我正在使用tkinter在python中編寫應用程序。在這個應用程序中,我試圖發送一批電子郵件,並且我希望在發送時顯示進度條。我可以創建進度條並啓動它,但是當電子郵件正在發送時,該欄會停止移動(如果它在電子郵件發送之前啓動,我希望在發送電子郵件之前啓動該欄,但它只是掛起,沒事的時候我不喜歡這樣的欄上移動。發送郵件時TTK進度條被阻止

startProgressBar() 
sendEmails() 
stopProgressBar() 

我試圖把郵件發送到一個單獨的線程,但我似乎沒有要任何運氣。我我正在使用高級的線程模塊,有什麼建議可以做什麼?也許我沒有得到正確的線程部分。我正在使用smtplib發送電子郵件。

回答

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

這應該適合你。 希望它有幫助:)

+0

我試過用我的代碼,我仍然有同樣的問題。我認爲問題在於,當電子郵件發送時,整個過程「暫停」。也許我需要找到一個更好的方式來做發送部分。 – apatrick 2011-12-24 01:47:05

0

我已經重新在我的應用程序更新中的這個問題。我已經使用Swing將UI轉換爲jython項目。

無論如何,我認爲使用觀察者模式是解決我的問題的最簡單方法。併發線程對我的項目來說不是必需的,我只是想給出一個近似的進度視圖。 Observer模式非常適合我的需求,而Observer模式的Java實現特別有用。

相關問題