Como alterar o cursor para a ampulheta em um aplicativo gtk3 python

4

Eu tenho uma função que leva muito tempo para executar e estou tentando mudar o cursor para uma ampulheta durante o tempo em que a função é executada. Mas só funciona a primeira vez que a função é chamada. Estou fazendo isso (está em um manipulador de eventos on_click de um botão):

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)
A janela

é uma janela criada com o Glade / GtkBuilder e com o nome ... window. Eu obtenho um controle sobre isso no __init__() da classe da janela assim:

self.window = self.builder.get_object('window')

Como eu disse, a ampulheta aparece apenas na primeira vez em que clico no botão. A segunda vez não funciona mais. Então estou fazendo errado. Mas o que estou fazendo errado?

    
por Michel Leunen 17.05.2012 / 12:52

1 resposta

3

Aqui está um exemplo prático do que você quer.

Você precisa compreender o conceito do que o loop principal do GTK faz para entender por que é importante separar o código de manipulação da GUI do código de bloqueio longo. Espero que os comentários e as instruções de depuração no meu exemplo ajudem você a entender. Esta entrada de FAQ do PyGTK é útil, e o conceito se aplica ao Python com GTK3 e GObject introspecção também.

Exemplo de código:

Este código cria uma janela com um simples botão chamado "Clique-me". Depois que você clicar nele, ele será alterado para "Trabalhando", o cursor se tornará uma ampulheta e a GUI permanecerá responsiva. Decorridos dez segundos, o rótulo do botão mudará para "Concluído" e o cursor retornará ao normal.

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()
    
por Flimm 16.11.2012 / 18:51