Gtk 如何在PyGObject中使用按钮暂停循环?

Gtk 如何在PyGObject中使用按钮暂停循环?,gtk,pygobject,Gtk,Pygobject,我有一个按钮,可以运行循环并相应地更新窗口。我想要另一个“暂停”按钮来暂停这个循环,但在循环运行时,我似乎无法做到这一点。也许线程是解决方案(我尝试了GLib.timeout\u add\u seconds,但没有成功)-什么是最简单的方法来实现这一点? 我已附上我的错误代码: import sys from time import sleep import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk cl

我有一个按钮,可以运行循环并相应地更新窗口。我想要另一个“暂停”按钮来暂停这个循环,但在循环运行时,我似乎无法做到这一点。也许线程是解决方案(我尝试了GLib.timeout\u add\u seconds,但没有成功)-什么是最简单的方法来实现这一点? 我已附上我的错误代码:

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

class LoopButton(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("Run")
        button.connect("clicked", self.on_click)
        self.pack_start(button, True, True, 0)

    def on_click(self, widget):
        msg = int(self.message)
        while self.GUI.is_paused == False:
            self.GUI.restart_window(str(msg))
            msg += 1
            while Gtk.events_pending():
                Gtk.main_iteration()
            sleep(1)
        self.GUI.is_paused = True

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

        self.GUI = GUI
        self.set_border_width(10)

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

    def on_click(self, widget):
        self.GUI.is_paused = True


class GUI:

    def __init__(self):
        self.is_paused = False
        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(LoopButton(self), True, True, 0)
        self.box.pack_start(PauseButton(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())

根据您在循环中真正做了什么,可能会有更多必要的细节,但下面是一个在GLib/Gtk中通常如何避免循环的示例。此方法的警告是:A)一次迭代必须足够快,以不影响UI更新(最多几毫秒)。B) 计时不准确:在上一次调用后的2秒钟内可能不会调用timeout函数

import gi
from gi.repository import GLib

class GUI:
    def __init__(self):
        # initialize the UI here...

        # setup updates every two seconds
        GLib.timeout_add_seconds(2, self.timeout_update)

    def timeout_update(self):
        # update your widgets here
        print ("Updating UI now...")

        # yes, we want to be called again
        return True

这和问题一样吗?您的实际代码在循环中做什么?答案取决于此。@jku不,不是。这非常相似,我修改了代码,但我问了如何暂停循环,而另一个问题没有do@andlabs为什么这很重要?我认为答案不应该取决于我在做什么。如果它确实相关,我将使用一个名为graph tool的包,创建一个新的图形并显示它,以及其他依赖于该图形的小部件。我的实际代码有点复杂/难以理解,所以这个问题的答案(如何用按钮暂停循环)应该可以回答我的实际代码问题。@Billjoe andlabs这样问是因为你不能在GTK主线程中执行长循环。您应该做什么取决于循环执行的任务类型。通常可以避免循环,而是使用超时、空闲处理程序或异步库调用。有时候你真的需要使用另一个线程来运行循环。太好了,现在可以了。我之前也尝试过使用timeout\u add\u seconds,但我没有返回True,这使得它无法正常运行。