为什么我在PyGObject中的onclick函数中没有循环?

时间:2017-07-05 02:16:32

标签: gtk pygobject

我正在使用PyGObject创建一个用户界面,我希望程序能够运行"运行"单击按钮时的循环并相应地刷新窗口。例如,在下面的代码中,我希望程序 - 单击按钮 - 用数字更新标签,休眠1秒,增加数字并再次使用数字更新标签等。当前程序但是,只显示最后的变化(循环结束后)。每次迭代循环时,如何对标签显示更改。请注意,这是我的问题的简化版本,所以我将非常感谢如何在按钮的onclick函数的循环内显示窗口的每个更新的一般解决方案。 我在下面附上了我的(错误的)代码:

import sys
from time import sleep
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

class SpecialButton(Gtk.Box):

    def __init__(self, GUI):
        Gtk.Box.__init__(self)

        self.GUI = GUI
        self.set_border_width(10)
        self.message = "1"

        button = Gtk.Button.new_with_label("Change label")
        button.connect("clicked", self.on_click)
        self.pack_start(button, True, True, 0)

    def on_click(self, widget):
        msg = int(self.message)
        for i in range(5):
            self.GUI.restart_window(str(msg))
            msg += 1
            sleep(1)

class GUI:

    def __init__(self):
        self.win = Gtk.Window()
        self.window_grid = Gtk.Grid()
        self.box = Gtk.Box(spacing=10)
        self.label = Gtk.Label("Default label")
        self.win.connect("delete-event", Gtk.main_quit)
        self.start_window()

    def start_window(self):
        self.box.pack_start(SpecialButton(self), True, True, 0)
        self.window_grid.add(self.box)
        self.window_grid.add(self.label)
        self.win.add(self.window_grid)
        self.win.show_all()

    def restart_window(self, label="Default label"):
        self.window_grid.destroy()
        self.window_grid = Gtk.Grid()
        self.box = Gtk.Box(spacing=10)
        self.label = Gtk.Label(label)
        self.start_window()

def main():
    app = GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

1 个答案:

答案 0 :(得分:0)

重要的是不要在主线程上运行任何类型的阻塞代码,因为它会剥夺您使用的任何GUI库的机会来执行保持UI看起来干净和清晰的重要工作。在这种情况下,它不是真正的循环问题,而是对time.sleep的调用,它会阻塞。也许尝试使用click处理程序启动工作线程来运行循环,或者开始涉及到asyncio.sleep的非阻塞调用的异步进程。