时间.sleep()在命令中以错误的顺序发生;总是在功能的开头

时间:2015-06-24 19:57:07

标签: python python-3.x gtk

以下代码是我正在处理的小型应用程序的精简版(为清晰起见);申请儿童拼写单词。

问题

我遇到的问题是函数flash_correct();它的目的是显示一个单词5秒钟,然后再次隐藏。

我必须有一个愚蠢的盲点,但无论我把time.sleep(5)放在哪里,该函数都以5秒的中断开始,而条目:self.entry2永远不会出现:

enter image description here

但是没有time.sleep(5),它会正确显示:

enter image description here

我的盲点在哪里?

(简化)代码:

#!/usr/bin/env python3
from gi.repository import Gtk, Pango, Gdk
import subprocess
import time


class InterFace(Gtk.Window):

    def __init__(self):

        Gtk.Window.__init__(self, title="Woorden raden")
        maingrid = Gtk.Grid()
        self.add(maingrid)
        maingrid.set_border_width(10)

        self.entry2 = Gtk.Entry()
        self.entry2.set_size_request(500,60)
        self.entry2.set_child_visible(False)
        self.entry2.modify_font(Pango.FontDescription('Ubuntu 30'))
        maingrid.attach(self.entry2, 0, 4, 4, 1)

        quitbutton = Gtk.Button("Stop", use_underline=True)
        quitbutton.modify_font(Pango.FontDescription('Ubuntu 20'))
        quitbutton.connect("clicked", self.on_close_clicked)
        maingrid.attach(quitbutton, 3, 7, 1, 1)

        showword_button = Gtk.Button("↺", use_underline=True)
        showword_button.modify_font(Pango.FontDescription('Ubuntu 25'))
        showword_button.connect("clicked", self.flash_correct)
        showword_button.set_size_request(60,20)
        maingrid.attach(showword_button, 0, 6, 1, 1)

    def flash_correct(self, button):
        # the time.sleep(5) seems to take place at the beginning
        # no matter in which order I set the commands
        self.entry2.set_text("Monkey")
        self.entry2.set_child_visible(True)
        time.sleep(5)
        self.entry2.set_child_visible(False)

    def on_close_clicked(self, button):
        Gtk.main_quit()


window = InterFace()
window.connect("delete-event", Gtk.main_quit)
window.set_default_size(330, 330)
window.set_resizable(False)
window.show_all()
Gtk.main()

2 个答案:

答案 0 :(得分:1)

您可以使用time.time隐藏大约5秒钟,在循环中调用Gtk.main_iteration(),以避免您的应用无响应。

def hide(self, time_lapse):
    start = time.time()
    end = start + time_lapse
    while end > time.time():
        Gtk.main_iteration()

def flash_correct(self, button):
    # the time.sleep(5) seems to take place at the beginning
    # no matter in which order I set the commands
    self.entry2.set_text("Monkey")
    self.entry2.set_child_visible(True)
    self.hide(5)
    self.entry2.set_child_visible(False)

pygtk faq 7中有一个很好的解释。How can I force updates to the application windows during a long callback or other internal operation?

  

如果您有一个长时间运行的回调或内部操作试图在执行期间递增地修改应用程序窗口,您会注意到这不会发生;应用程序的窗口会冻结持续时间。

     

这是设计的:所有gtk事件(包括窗口刷新和更新)都在mainloop中处理,当你的应用程序或回调代码运行时,mainloop无法处理窗口更新事件。因此,应用程序窗口中不会发生任何事情。

     

这里的技巧是要意识到你的操作可能需要一段时间才能返回,或者它在哪里动态地改变窗口内容,并在你希望更新强制输出的地方添加这样的代码片段:

while gtk.events_pending():
   gtk.main_iteration(False)
  

这告诉gtk处理任何已挂起的窗口事件。例如,如果您的处理程序有一个长循环,那么将此代码段作为循环的一部分插入将避免它挂起窗口,直到回调结束。

     

更有说服力的是,用伟大的马尔科姆·特雷德尼克(Malcolm Tredinnick)的话来说,“这需要使用所谓的”秘密技术#1让你的应用看起来更具响应性“(tm):

添加while gtk.events_pending():也可能没有害处。

答案 1 :(得分:1)

最好使用与主循环集成的计时器,而不是忙碌等待直到时间结束。幸运的是,GLib中只有这样的设施:

def flash_correct(self, button):
    self.entry2.set_text("Monkey")
    self.entry2.set_child_visible(True)
    GLib.timeout_add_seconds(5, self.flash_end)

def flash_end(self):
    self.entry2.set_child_visible(False)
    return GLib.SOURCE_REMOVE