我有一个函数需要很长时间才能执行,我试图在函数执行期间将光标更改为沙漏。但它只在第一次调用该函数时有效。我正在这样做(它在按钮的 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)
__init__()
window 是一个使用 Glade/GtkBuilder 构建的窗口,名为...window。我在窗口类中获取了它的句柄,如下所示:
self.window = self.builder.get_object('window')
正如我所说,沙漏仅在我第一次点击按钮时出现。第二次它不再起作用。所以我做错了。但我做错了什么?
答案1
这是您想要的一个有效示例。
您需要掌握 GTK 主循环的概念,才能理解将 GUI 操作代码与长阻塞代码分开的重要性。希望我的示例中的注释和调试语句能帮助您理解。这PyGTK 常见问题解答很有用,并且这个概念也适用于具有 GTK3 和 GObject 自省的 Python。
示例代码:
此代码创建一个窗口,其中有一个标有“单击我”的简单按钮。单击该按钮后,它将变为“正在工作”,光标将变为沙漏,并且 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()