我正在使用tkinter在python中编写应用程序。在这个应用程序中,我试图发送一批电子邮件,我想在发送时显示进度条。我可以创建进度条并启动它,但是当发送电子邮件时,栏会停止移动(如果它是在发送电子邮件之前启动的话,我想在发送电子邮件之前启动栏,但是当我这样做的时候它就会挂起并且没有任何动作。
startProgressBar()
sendEmails()
stopProgressBar()
我已尝试将电子邮件发送到单独的帖子中,但我似乎没有任何运气。我正在使用高级线程模块。有什么建议吗?也许我没有让线程部分正确。我正在使用smtplib发送电子邮件。
答案 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实现特别有用。