如何在python gtk3应用程序中将光标更改为沙漏

Mic*_*nen 5 python cursor gtk3

我有一个需要很长时间才能执行的函数,并且我试图在执行函数期间将光标更改为沙漏。但它只在第一次调用函数时有效。我正在这样做(它在按钮的 on_click 事件处理程序中):

from gi.repository import Gtk, Gdk, GObject
import time

def on_grabbtn_clicked(self, button):
    # Change the cursor to hour Glass
    cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH)
    self.window.get_root_window().set_cursor(cursor)

    # lenghty process here
    time.sleep(10)

     # Set the cursor to normal Arrow
    cursor = Gdk.Cursor.new(Gdk.CursorType.ARROW)
    self.window.get_root_window().set_cursor(cursor)
Run Code Online (Sandbox Code Playgroud)

window 是一个使用 Glade/GtkBuilder 构建的窗口,名为...window。我__init__()在窗口类中得到了一个句柄,如下所示:

self.window = self.builder.get_object('window')
Run Code Online (Sandbox Code Playgroud)

正如我所说,沙漏仅在我第一次单击按钮时出现。第二次就不行了。所以我做错了。但我做错了什么?

Fli*_*imm 5

这是您想要的一个工作示例。

您需要掌握 GTK 主循环的作用的概念,才能理解为什么将 GUI 操作代码与长阻塞代码分开很重要。希望我的示例中的注释和调试语句能够帮助您理解。这个PyGTK FAQ 条目很有用,这个概念也适用于带有 GTK3 和 GObject 自省的 Python。

示例代码:

此代码创建一个窗口,其中带有一个标记为“Click me”的简单按钮。单击它后,它将更改为“正在工作”,光标将变为沙漏,并且 GUI 将保持响应状态。十秒过去后,按钮标签将更改为“完成”,光标将恢复正常。

import time
import threading

from gi.repository import Gtk, Gdk, GObject

window = None

def main():
    GObject.threads_init()
    Gdk.threads_init()

    # Build GUI:
    global window
    window = Gtk.Window()
    button = Gtk.Button(label="Click me")
    window.add(button)
    window.set_default_size(200, 200)
    window.show_all()

    # Connect signals:
    window.connect("delete-event", Gtk.main_quit)
    button.connect("clicked", on_button_click)

    Gtk.main()

def on_button_click(button):
    print "Debug on_button_click: current_thread name:", threading.current_thread().name

    # This is a callback called by the main loop, so it's safe to
    # manipulate GTK objects:
    watch_cursor = Gdk.Cursor(Gdk.CursorType.WATCH)
    window.get_window().set_cursor(watch_cursor)
    button.set_label("Working...")
    button.set_sensitive(False)

    def lengthy_process():
        print "Debug lengthy_process: current_thread name:", threading.current_thread().name
        # We're in a new thread, so we can run lengthy processes without
        # freezing the GUI, but we can't manipulate GTK objects except
        # through GObject.idle_add
        time.sleep(10)
        def done():
            print "Debug done: current_thread name:", threading.current_thread().name
            window.get_window().set_cursor(None)
            button.set_label("Done!")
            return False
        GObject.idle_add(done)

    thread = threading.Thread(target=lengthy_process)
    thread.start()
        
if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)