J'ai une fonction qui prend beaucoup de temps à exécuter et j'essaie de changer le curseur en un sablier pendant l'exécution de la fonction. Mais cela ne fonctionne que la toute première fois que la fonction est appelée. Je fais ceci (c'est dans un gestionnaire d'événement on_click d'un bouton):
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)
window est une fenêtre construite avec Glade/GtkBuilder et nommée ... window. Je reçois une poignée dessus dans la __init__()
de la classe window comme ceci:
self.window = self.builder.get_object('window')
Comme je l'ai dit, le sablier n'apparaît que la première fois que je clique sur le bouton. La deuxième fois, ça ne marche plus. Alors je le fais mal. Mais qu'est-ce que je fais mal?
Voici un exemple de travail de ce que vous voulez.
Vous devez comprendre le concept de la boucle principale GTK pour comprendre pourquoi il est important de séparer le code de manipulation d'interface graphique du code de blocage long. Espérons que les commentaires et les instructions de débogage de mon exemple vous aideront à comprendre. Cette entrée PyGTK FAQ est utile, et le concept s’applique également à Python avec l’introspection de GTK3 et de GObject.
Ce code crée une fenêtre avec un simple bouton intitulé "Cliquez-moi". Une fois que vous cliquez dessus, il passera à "Working", le curseur deviendra un sablier et l'interface graphique restera sensible. Une fois que dix secondes se sont écoulées, le libellé du bouton deviendra "Terminé" et le curseur reviendra à la normale.
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 __== "__main__":
main()