Jak tworzyć i używać skrótów klawiaturowych w opracowywanej przeze mnie aplikacji Gtk?

9

Szybko tworzę aplikację dla Ubuntu App Showdown w Python + Gtk. Nazywam to Discvur. Chciałbym załączyć niektóre skróty klawiaturowe.

Przeszukując sieć, znalazłem tę stronę o AccelGroup i tę stronę o gtk_widget_add_accelerator, ale nie rozumiem, jak zacząć. Czy możesz mi powiedzieć, jak zdefiniowałbym odpowiedni sygnał, a następnie używał go w mojej aplikacji?

Agmenor
źródło
Pierwszy link jest zepsuty ...
WinEunuuchs2Unix

Odpowiedzi:

8

Oto kilka fragmentów kodu z jednej z moich aplikacji Python + Gtk, dodatkowo rozszerzonych zgodnie z komentarzami do tej odpowiedzi:

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
źródło
Dziękuję, ale mam ten błąd: self.add_accelerator(self.quick_add_entry, "<Control>l", signal="grab-focus") AttributeError: 'DiscvurWindow' object has no attribute 'quick_add_entry'. Gdy próbuję wyszukać w sieci hasło „szybkie_adres_wszelkie”, nie mogę go nigdzie znaleźć. Czy na pewno jest to właściwa funkcja? Gdzie mogę znaleźć więcej informacji / samouczek do tego? Ponadto, czy „<Control> l” oznacza Ctrl + l, czy jest to błąd?
Agmenor,
To nie jest funkcja, to tylko nazwa widżetu, do którego podłączasz akcelerator. Poprawiłem to, aby było jaśniejsze.
Bryce,
Dziękuję za Twoją odpowiedź. Po pierwsze, mogłem zmienić „GTK” na „Gtk”. Po drugie, kiedy uruchamiam kod, pojawia się komunikat „NameError: nazwa globalna„ DEBUG ”nie jest zdefiniowana”, więc przypuszczam, że jest to zmienna z twojego skryptu. Skomentowałem to więc we własnym skrypcie. Po trzecie, po skomentowaniu, pojawia się błąd „AttributeError: Obiekt„ DiscvurWindow ”nie ma atrybutu„ akceleratory ””. Przykro mi, jeśli ma to być oczywiste, ale dokumentacja wciąż jest dla mnie niejasna; w szczególności dokumentacja mówi, że add_accelerator potrzebuje 6 argumentów?
Agmenor
Racja, musisz sam stworzyć akceleratory; Zaktualizowałem przykład, aby pokazać, jak to zrobić.
Bryce
Po krótkich badaniach i nieudanych próbach mogłem uzyskać działający skrypt. Czy możesz to zweryfikować? Jeśli uważasz, że jest to poprawne, zmienię (lub możesz) twoją odpowiedź: paste.ubuntu.com/1053516 . Bardzo doceniam twoją recenzję, Bryce. „Małe badania” były eufemizmem, ale przypuszczam, że lepiej jest nauczyć człowieka, jak łowić, niż dawać mu ryby. Dziękuję jeszcze raz.
Agmenor
6

Oto kod, który w końcu zadziałał. Ponieważ zależy to w dużej mierze od mojego środowiska programistycznego Quickly + Glade + Python + Gtk, robię z tego niezależną odpowiedź. Odpowiedź Bryce'a bardzo pomogła, podobnie jak moja wymiana z aking1012 .

Rzeczywisty kod w edytorze tekstu:

# 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."

W Glade utworzyłem GtkEntry o nazwie „entry1” w moim oknie o nazwie „discvur_window”. W zakładce „Sygnały” nadałem sygnałowi „backspace” moduł obsługi o nazwie „on_erasing”.

Teraz, naciśnięcie Backspacelub Ctrl+ Bpowoduje, że terminal wypisuje „To działa”.

Agmenor
źródło
Czy można tego użyć, aby wyłączyć skrót Ctrl + F4, aby zamknąć okno?
Juzer Ali
Masz na myśli Alt + F4? Nie wiem, nie próbowałem.
Agmenor,
Miałem na myśli zarówno Ctrl + F4, jak i Alt + F4
Juzer Ali
2

Przepakowałem podane odpowiedzi w tym wątku do samodzielnego przykładu:

#!/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()

Dostępne również jako gist: https://gist.github.com/thorsummoner/230bed5bbd3380bd5949

Uwaga: Domyślnym sygnałem jest clickednie activatedlatego , że aplikacje nigdy nie powinny łączyć się z ::activatesygnałem, ale używać ::clickedsygnału Gtk.Button .

ThorSummoner
źródło
Więc zauważyłem; podczas używania clickedakceleratora można bardzo szybko zmiażdżyć, ale przycisk nie naciska wizualnie. Podczas używania activateprzycisk zostanie wciśnięty, ale akcelerator można nacisnąć dopiero po zakończeniu wizualnego wciśnięcia.
ThorSummoner,