Como crio e uso atalhos de teclado em um aplicativo Gtk que estou desenvolvendo?

9

Estou criando um aplicativo para o Ubuntu App Showdown em Python + Gtk com rapidez. Estou chamando de Discvur. Eu gostaria de incluir alguns atalhos de teclado.

Pesquisando na web, encontrei esta página sobre o AccelGroup e esta página sobre o gtk_widget_add_accelerator, mas não entendo como começar. Você poderia me dizer como eu definiria um sinal apropriado e o usaria no meu aplicativo?

Agmenor
fonte
O primeiro link está quebrado ...
WinEunuuchs2Unix 02/01

Respostas:

8

Aqui estão alguns bits de código de um dos meus aplicativos Python + Gtk, estendidos ainda mais de acordo com os comentários a esta resposta:

self.my_accelerators = Gtk.AccelGroup()
self.entry = Gtk.builder.get_object("entry1")
self.add_accelerator(self.entry, "<Control>b", signal="backspace")
...

def add_accelerator(self, widget, accelerator, signal="activate"):
    """Adds a keyboard shortcut"""
    if accelerator is not None:
        #if DEBUG:
            #print accelerator, widget.get_tooltip_text()
        key, mod = Gtk.accelerator_parse(accelerator)
        widget.add_accelerator(signal, self.my_accelerators, key, mod, Gtk.AccelFlags.VISIBLE)
Bryce
fonte
Obrigado, mas eu tenho esse erro: self.add_accelerator(self.quick_add_entry, "<Control>l", signal="grab-focus") AttributeError: 'DiscvurWindow' object has no attribute 'quick_add_entry'. Quando tento uma pesquisa na Web de "quick_add_entry", não consigo encontrá-la em nenhum lugar. Tem certeza de que é a função correta? Onde posso encontrar mais informações / um tutorial para isso? Além disso, "<Control> l" significa Ctrl + l ou é um tipo de erro?
Agmenor
Não é uma função, é apenas o nome de qualquer widget ao qual você está conectando o acelerador. Revisei para ficar mais claro.
Bryce
Obrigado pela sua resposta. Primeiro, tomei a liberdade de mudar o "gtk" para "Gtk". Segundo, quando executo seu código, obtenho "NameError: o nome global 'DEBUG' não está definido", portanto, suponho que essa seja uma variável do seu próprio script. Então eu comentei no meu próprio script. Terceiro, depois de comentá-lo, recebo o erro "AttributeError: 'DiscvurWindow' objeto não tem atributo 'aceleradores'". Lamento se isso é evidente, mas a documentação ainda é obscura para mim; em particular, a documentação diz que add_accelerator precisa de 6 argumentos?
precisa saber é o seguinte
Certo, você precisa criar aceleradores; Atualizei o exemplo para mostrar como.
Bryce
Depois de um pouco de pesquisa e tentativas fracassadas, eu consegui um script de trabalho. Você poderia verificar isso? Se você acha que está correto, vou (ou você pode) modificar sua resposta: paste.ubuntu.com/1053516 . Eu apreciaria muito sua crítica, Bryce. "Um pouco de pesquisa" era um eufemismo, mas suponho que é melhor aprender um homem a pescar do que dar-lhe peixe. Então, obrigado novamente.
Agmenor
6

Aqui está o código que finalmente funcionou. Como depende muito do meu ambiente de desenvolvimento Rapidamente + Glade + Python + Gtk, eu a faço uma resposta independente. A resposta de Bryce ajudou muito, assim como minhas trocas com aking1012 .

O código real, em um editor de texto:

# Accelerators
self.my_accelerators = Gtk.AccelGroup()
self.window = self.builder.get_object("discvur_window")
self.window.add_accel_group(self.my_accelerators)
self.entry = self.builder.get_object("entry1")
self.add_accelerator(self.entry, "<Control>b", signal="backspace")



def add_accelerator(self, widget, accelerator, signal="activate"):
    """Adds a keyboard shortcut"""
    if accelerator is not None:
        #if DEBUG:
            #print accelerator, widget.get_tooltip_text()
        key, mod = Gtk.accelerator_parse(accelerator)
        widget.add_accelerator(signal, self.my_accelerators, key, mod, Gtk.AccelFlags.VISIBLE)
        print "The accelerator is well added with the signal " + signal

def on_erasing(self, widget):
    print "It works."

No Glade, criei um GtkEntry chamado "entry1" na minha janela chamado "discvur_window". Na guia 'Signals', dei ao sinal "backspace" um manipulador chamado "on_erasing".

Agora, pressionar Backspaceou Ctrl+ Bfaz com que o terminal imprima "Funciona".

Agmenor
fonte
Isso pode ser usado para desativar o atalho Ctrl + F4 para fechar a janela?
precisa saber é o seguinte
Você quer dizer Alt + F4? Não sei, não tentei.
Agmenor 03/09/12
Eu quis dizer tanto Ctrl + F4 e Alt + F4
Juzer Ali
2

Reembalei as respostas fornecidas neste tópico em um exemplo independente:

#!/usr/bin/env python2

import signal

from gi.repository import Gtk

def bind_accelerator(accelerators, widget, accelerator, signal='clicked'):
    key, mod = Gtk.accelerator_parse(accelerator)
    widget.add_accelerator(signal, accelerators, key, mod, Gtk.AccelFlags.VISIBLE)

def on_recompute_base_encryption_key_hash(widget):
    print 'Thinking... (This could take forever)'

def main():

    if 'gtk':
        window = Gtk.Window()
        window.connect("delete-event", Gtk.main_quit)

        if 'accelerator-demo':
            # Accelerators
            accelerators = Gtk.AccelGroup()
            window.add_accel_group(accelerators)

            # Widget
            target_widget = Gtk.Button('Recompute Base Encryption Key Hash')
            target_widget.connect('clicked', on_recompute_base_encryption_key_hash)
            window.add(target_widget)

            # Bind
            bind_accelerator(accelerators, target_widget, '<Control>b')

        window.show_all()
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        Gtk.main()

if __name__ == '__main__':
    main()

Também disponível como essência: https://gist.github.com/thorsummoner/230bed5bbd3380bd5949

Nota: O sinal padrão é clicked, não activateporque os Aplicativos nunca devem se conectar ao ::activatesinal, mas use o ::clickedsinal Gtk.Button .

ThorSummoner
fonte
Então eu notei; ao usar clickedo acelerador pode ser esmagado muito rapidamente, mas o botão não pressiona visualmente. Ao usar activate, o botão pressiona, mas o acelerador só pode ser pressionado quando a pressão visual terminar.
precisa saber é o seguinte