为什么我不能在PyGObject的onclick函数中有一个循环? [英] Why can't I have a loop in the onclick function in PyGObject?

查看:148
本文介绍了为什么我不能在PyGObject的onclick函数中有一个循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am creating a user interface using PyGObject and I want the program to "run" a loop when a button is clicked and refresh the window accordingly. For example, in the following code, I want the program - on the click of the button - to update the label with a number, sleep for 1 second, increment the number and update the label again with the number, etc. The program currently, however, just shows the changes at the very end (after the loop is finished). How do I make the changes to the label show every time I iterate over the loop. Note that this is a simplified version of my question so I would appreciate a general solution to how to doing showing every update to the window inside a loop of the onclick function of a button. I have attached my (faulty) code below:

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())


推荐答案

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

It's important not to run any kind of blocking code on the main thread because it takes away the opportunity of whatever GUI library you're using to perform the vital work of keeping the UI looking clean and crisp. In this case, it's not really the loop that's the problem, but the call to time.sleep, which blocks. Perhaps try using the the click handler to start a worker thread to run the loop, or begin an asynchronous process involving non-blocking calls to asyncio.sleep.

这篇关于为什么我不能在PyGObject的onclick函数中有一个循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆