Python 2.7 kivy函数执行顺序中的奇怪行为
以下方法绑定到一个发送按钮,该按钮应使用Python的SMTP库发送电子邮件。我想要的是,我的屏幕上的标签在发送邮件之前显示“发送…”文本,然后在发送邮件之后,弹出窗口将显示邮件已发送的文本。我面临的问题是,按下按钮后什么也没有发生(标签文本不显示),过了一会儿(邮件发送的正常时间),弹出窗口显示,标签中的文本显示。。。我很奇怪,所有输出都同时显示,而不是正常顺序: 在标签>发送邮件>显示邮件发送后的弹出窗口中显示文本 我的代码如下:Python 2.7 kivy函数执行顺序中的奇怪行为,python-2.7,kivy,Python 2.7,Kivy,以下方法绑定到一个发送按钮,该按钮应使用Python的SMTP库发送电子邮件。我想要的是,我的屏幕上的标签在发送邮件之前显示“发送…”文本,然后在发送邮件之后,弹出窗口将显示邮件已发送的文本。我面临的问题是,按下按钮后什么也没有发生(标签文本不显示),过了一会儿(邮件发送的正常时间),弹出窗口显示,标签中的文本显示。。。我很奇怪,所有输出都同时显示,而不是正常顺序: 在标签>发送邮件>显示邮件发送后的弹出窗口中显示文本 我的代码如下: def send_email(self): self
def send_email(self):
self.the_mail_feedback.text = "Sending..."#this is not showing at first but after execution!
gmail_user = str(self.txt_from_mail.text)
gmail_pwd = str(self.txt_password.text)
FROM = str(self.txt_from_mail.text)
TO = []
TO.append(str(self.txt_to_mail.text))
SUBJECT = "subject 1"
TEXT = "some text..."
message = """\From: %s\nTo: %s\nSubject:
%s\n\n%s""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
self.pop.open()#a popup that says that the mail is sent...
#self.the_mail_feedback.text="" #will uncomment when it works to reset feedback
except:
self.the_mail_feedback.text="Failed To Send Mail... Check Credentials
“问题是,所有这些操作都发生在同一个线程,即主程序循环中。因此,例如,第二行确实更改了标签文本,但用户界面不会更新,直到函数完成并将控件释放到正常的kivy eventloop。eventloop然后更新标签的图形表示 因此,实际上一切都是按顺序进行的,只是在功能完成之前,图形无法自由更新,此时一切都会立即发生。出于同样的原因,您会发现在邮件发送时无法进行任何触摸输入 为了避免这种情况,您需要使用eventloop,并允许正常的kivy控制流继续运行。下面是一个我认为应该有效的快速示例:
def begin_send_email(self):
self.the_mail_feedback.text = "Sending..."#this is not showing at first but after execution!
Clock.schedule_once(self.finish_send_email, 0)
def finish_send_email(self, *args):
gmail_user = str(self.txt_from_mail.text)
gmail_pwd = str(self.txt_password.text)
FROM = str(self.txt_from_mail.text)
TO = []
TO.append(str(self.txt_to_mail.text))
SUBJECT = "subject 1"
TEXT = "some text..."
message = """\From: %s\nTo: %s\nSubject:
%s\n\n%s""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
self.pop.open()#a popup that says that the mail is sent...
#self.the_mail_feedback.text="" #will uncomment when it works to reset feedback
except:
self.the_mail_feedback.text="Failed To Send Mail... Check Credentials
当然,也有其他方法来构造它,但一般的想法是,函数不锁定事件循环,而是更新标签文本,然后在将控制权交还给eventloop之前安排更多的任务。eventloop然后执行其正常任务,包括在执行之前将图形标签设置为您想要的“发送…”正在终止预定功能以完成发送
您也可能会发现,从单独的线程发送电子邮件是必要的或有用的,以避免锁定用户界面,尽管它可能足够快,可以正常工作。您可以非常轻松地完成此操作,但必须小心仅在主线程中执行图形操作。谢谢,我明天将尝试(非常累)我确信这就是答案,因为我读了一些关于主循环的文章,现在对我来说很有意义。再次感谢。