странное поведение в порядке выполнения функции в kivy

Следующий метод привязан к кнопке отправки, которая должна отправлять электронное письмо с использованием библиотеки SMTP Python. Я хочу, чтобы метка на моем экране отображала текст «отправка ...» перед отправкой почты, а после отправки почты во всплывающем окне будет отображаться текст о том, что почта была отправлена. Проблема, с которой я сталкиваюсь, заключается в том, что после нажатия кнопки ничего не происходит (текст метки не отображается), а через мгновение (обычное время отправки почты) всплывающее окно отображается, и текст в метке отображается... Это для меня очень странно, что все выходные данные отображаются одновременно, а не в обычном порядке:

отображать текст в ярлыке> отправить почту> показать всплывающее окно после отправки почты.

Мой код выглядит следующим образом:

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

"


person toufikovich    schedule 26.11.2013    source источник


Ответы (1)


Проблема в том, что все эти операции происходят в одном потоке, основном цикле программы. Так, например, ваша вторая строка действительно меняет текст метки, но пользовательский интерфейс не обновляется до тех пор, пока ваша функция не завершится и не передаст управление обычному циклу событий kivy. Затем цикл событий обновляет графическое представление метки.

Так что на самом деле все происходит по порядку, просто графика не может обновляться бесплатно, пока функция не завершится, после чего все происходит сразу. По той же причине вы обнаружите, что не можете выполнять сенсорный ввод во время отправки почты.

Чтобы избежать этого, вам нужно работать с циклом событий и оставлять места для продолжения нормального потока управления 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

Конечно, есть и другие способы структурировать его, но общая идея заключается в том, что вместо блокировки цикла обработки событий функция обновляет текст метки, а затем планирует еще несколько задач, прежде чем передать управление обратно циклу обработки событий. Затем цикл обработки событий выполняет свои обычные задачи, включая установку графической метки на «Отправка...», как вы хотите, прежде чем выполнять запланированную функцию для завершения отправки.

Вы также можете счесть необходимым или полезным посмотреть на отправку электронной почты из отдельного потока, чтобы избежать блокировки пользовательского интерфейса, хотя это может быть достаточно быстро, чтобы все было в порядке. Вы можете сделать это довольно легко, хотя вам нужно быть осторожным, чтобы выполнять графические операции только в основном потоке.

person inclement    schedule 26.11.2013
comment
спасибо, я попробую это завтра (очень устал), и я уверен, что это ответ, потому что я немного читал об основном цикле, и теперь это имеет смысл для меня. еще раз спасибо. - person toufikovich; 26.11.2013