【问题标题】:PyGObject - GtkSpinner is not spinning when I call a function - Why?PyGObject - 当我调用函数时,GtkSpinner 没有旋转 - 为什么?
【发布时间】:2018-08-30 21:17:02
【问题描述】:

我有一个简单的 Python/GTK 应用程序。我有一个做事的函数,直到所说的函数完成做事,GtkSpinner 应该是旋转的。

这是我的代码:

import time
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class Handler:

def on_main_window_destroy(self, *args):
    Gtk.main_quit()

def on_button_clicked(self, *args):
    print("button clicked")
    self.dostuff()

def dostuff(self):
    app.spinner.start()
    print("I'm doing stuff")
    time.sleep(3)
    print("I'm done")
    app.spinner.stop()

class MainApp():

def __init__(self):
    self.builder = Gtk.Builder()
    self.builder.add_from_file("test.glade")
    self.builder.connect_signals(Handler())
    self.main_window = self.builder.get_object("main_window")
    self.main_window.show()

    self.spinner = self.builder.get_object("spinner")

def main(self):
    Gtk.main()

if __name__ == "__main__":
app = MainApp()
app.main()

time.sleep() 命令不是问题。如果我用实际的“工作”替换它,同样的事情也会发生。 Spinner 未启动/激活。

这是为什么呢?每个命令都是逐行处理的。那么有什么东西会阻塞呢?如果我用简单的 print() 语句替换 Spinner 代码,它们会按照您的预期输出。我没有CS学位,我只是一个业余爱好者。有什么我没有得到的概念吗?

我需要更改哪些内容,以便我的 Spinner 在任务开始之前启动并在任务完成后停止?

提前非常感谢!

编辑:这是我的 Glade 文件:https://pastebin.com/UDUinH1d

【问题讨论】:

  • 您的程序无法执行,因此很难知道哪里出了问题。微调器是否可见?请创建一个Minimal, Complete, and Verifiable example
  • 我将 Glade 文件添加到我的原始帖子中。它现在应该可以工作了!
  • 不,这不是没有任何努力,您应该发布一个开箱即用的非常小的示例
  • 对不起,我不明白。这已经是可能的最小示例了。我有一个更大的应用程序,只是做了这个简单的演示来显示问题所在。真的没有办法让它变得更小。你需要存档。我原始帖子中发布的 *.py 文件和您可以在 pastebin 链接中找到的 test.glade 文件。然后将两个文件放在一个目录中,然后运行 ​​Python 文件。 (显然你需要在 GTK Linux 环境中)
  • 由于缩进不正确,您的 Python 代码示例无法执行。很高兴您解决了自己的问题!

标签: gtk3 pygtk pygobject gtkspinner


【解决方案1】:

我自己想通了。由于某种原因(我不太明白),即使 Python 脚本应该逐行执行,GTK GUI 也没有响应。出于某种原因,这似乎不是 PyGObject 的情况。所以唯一的解决办法就是把它穿起来,现在看起来像这样:

    t = threading.Thread(target=dostuff, args=(optional, arguments, go, here))
    app.spinner.start()
    t.start()

【讨论】:

  • 这是有道理的,因为您的按钮单击处理程序是在 Gtk 主线程中执行的。这将冻结任何其他与 Gtk 相关的东西,除非您使用例如产生执行。 Gtk.main_iteration_do() 偶尔。也许这个问题也很有用:stackoverflow.com/questions/11923008/threading-in-gtk-python
  • 这适用于每个 GUI 框架。由于您的 dostuff 函数在主循环 (Gtk.main()) 内运行,因此它在同一线程中一次运行每一行,因此,虽然它是 time.sleeping,但它无法旋转 Spinner。您的解决方案是(AFAIK)正确的方法。
  • 是的,如果你正在从另一个线程操作 Gtk 东西(在这种情况下你不是),请务必使用 Gdk.threads_add_idle 或类似的东西。
  • '逐行'表示 C 语言中的 100 行。 Gtk.main() 不是“一行”。你应该考虑使用 Gtk 的 events_pending 和 main_iteration (developer.gnome.org/gtk3/stable/gtk3-General.html)
  • 但是如果我通过一个简单的 print() 语句替换 spinner-coed,那么 print() 语句实际上会打印出一些东西。那么为什么 print() 实际打印了一些东西,但 self.spinner.start() 没有启动微调器?我在这里没有得到什么?
【解决方案2】:

您在主代码中使用 ( time.sleep ),但 ( sleep ) 停止了所有脚本并开始旋转。我使用 ( thread ) 将其作为第二个进程启动。

检查一下。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time, gi, thread
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class MainApp():
    def __init__(self):
        self.builder = Gtk.Builder()
        self.builder.add_from_file("test.glade")
        self.main_window = self.builder.get_object("main_window")
        self.main_window.connect("destroy", self.quit);

        self.spinner = self.builder.get_object("spinner")

        self.button = self.builder.get_object("button")
        self.button.connect("clicked", self.on_button_clicked);

        self.main_window.show()

    def main(self): Gtk.main()
    def quit(self, widget): Gtk.main_quit();

    def sleep_and_stop(self, data = None):
        time.sleep(3);
        print("I'm done");
        self.spinner.stop();

    def on_button_clicked(self, widget = None, data = None):
        self.spinner.start();
        print("I'm doing stuff");
        thread.start_new_thread(self.sleep_and_stop, (None,));

if __name__ == "__main__": MainApp().main();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    相关资源
    最近更新 更多