9

I am creating an application for the Ubuntu App Showdown in Python + Gtk with quickly. I am calling it Discvur. I would have liked to include some keyboard shortcuts.

Searching the web, I found this page about AccelGroup and this page about gtk_widget_add_accelerator but I don't understand how to start with it. Could you tell me how I would define an appropriate signal and then use it in my application?

1

3 Answers 3

8

Here's some bits of code from one of my Python + Gtk apps, further extended according to the comments to this answer:

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)
11
  • Thank you but I got this error: self.add_accelerator(self.quick_add_entry, "<Control>l", signal="grab-focus") AttributeError: 'DiscvurWindow' object has no attribute 'quick_add_entry'. When I try a web search of "quick_add_entry", I cannot find it anywhere. Are you sure it is the right function? Where can I find more information/a tutorial for this? Additionally, does "<Control>l" mean Ctrl + l or is it a mistype?
    – Agmenor
    Jun 20, 2012 at 18:01
  • It's not a function, that's just the name of whatever widget you're connecting the accelerator to. I've revised it to be clearer.
    – Bryce
    Jun 20, 2012 at 19:06
  • Thank you for your answer. First, I took the liberty to change the "gtk" into "Gtk". Second, when I run your code I get "NameError: global name 'DEBUG' is not defined", so I suppose this is a variable from your own script. So I commented it in my own script. Third, after having commented it, I get the error "AttributeError: 'DiscvurWindow' object has no attribute 'accelerators'". I am sorry if this is supposed to be evident but the documentation is still obscure to me; in particular the documentation says add_accelerator needs 6 arguments?
    – Agmenor
    Jun 21, 2012 at 3:18
  • Right, you need to create accelerators yourself; I've updated the example to show how.
    – Bryce
    Jun 21, 2012 at 6:21
  • After a little research and failed tries, I could get a working script. Could you please verify it? If you think it is correct, I will (or you can) modify your answer: paste.ubuntu.com/1053516. I would appreciate your review a lot, Bryce. "A little research" was a euphemism, but I suppose it is better to learn a man how to fish than giving him fish. So thank you again.
    – Agmenor
    Jun 22, 2012 at 0:36
7

Here is the code that finally worked. As it depends highly on my development environment Quickly + Glade + Python + Gtk, I make it an independent answer. Bryce's answer helped a lot, and so did my exchanges with aking1012.

The actual code, in a text editor:

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

In Glade, I created a GtkEntry called "entry1" in my window called "discvur_window". In the 'Signals' tab, I gave the signal "backspace" a handler called "on_erasing".

Now, hitting Backspace or Ctrl+B makes the terminal print "It works.".

3
  • Can this be used to disable Ctrl+F4 shortcut to close the window?
    – Juzer Ali
    Sep 3, 2012 at 17:04
  • You mean Alt+F4 ? I don't know, I haven't tried.
    – Agmenor
    Sep 3, 2012 at 20:35
  • I meant both Ctrl+F4 and Alt+F4
    – Juzer Ali
    Sep 4, 2012 at 13:24
3

I've repackaged the given answers in this thread into a standalone example:

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

Also available as a gist: https://gist.github.com/thorsummoner/230bed5bbd3380bd5949

Note: The default signal is clicked, not activate because Applications should never connect to the ::activate signal, but use the Gtk.Button ::clicked signal.

1
  • So I noticed; when using clicked the accelerator can be mashed very quickly, but the button doesn't visually depress. When using activate, the button will depress, but the accelerator can only be pressed once the visual depress is finished. Jan 18, 2016 at 21:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .