How do I create and use keyboard shortcuts in a Gtk app that I am developing?

1,726

Solution 1

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

Solution 2

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)

Solution 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.

Share:
1,726

Related videos on Youtube

Cameron Laird
Author by

Cameron Laird

Updated on September 18, 2022

Comments

  • Cameron Laird
    Cameron Laird over 1 year

    I have made a search box so that you can enter the product id that you wish to gain the information of. When i input data in the product id box, there are no results returned, anyone know what im doing wrong? I think that 'while ($row = mysql_fetch_array($result)) {' is wrong but not too sure as everything ive tried didn't work.

      <div class="searchbox">
        <form action="Search.php" method="get">
           <fieldset>
           <input name="search" id="search" placeholder="Search for a Product" type="text" />
             <input id="submit" type="button" />
          </fieldset>
        </form>
     </div>
     <div id="content">
     <ul>        
     <?php
    
     // connect to the database
        include('base.php');
    
    
     $search = mysql_real_escape_string($_GET['search']);
     $query = "SELECT * FROM Product WHERE ProductID LIKE '%{$search}%'";
     $result = mysql_query($query); 
     while ($row = mysql_fetch_array($result)) {
     echo "<li><span class='name'><b>{$row['ProductID']}</b></span></li>";
     }
    
    • Admin
      Admin over 4 years
      The first link is broken...
  • Agmenor
    Agmenor almost 12 years
    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?
  • Bryce
    Bryce almost 12 years
    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
    Bryce almost 12 years
    Right, you need to create accelerators yourself; I've updated the example to show how.
  • Agmenor
    Agmenor almost 12 years
    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
    Agmenor almost 12 years
    I faced a big problem indeed with Gtk.ACCEL_VISIBLE… Should I try Gtk.Accelflags(ACCEL_VISIBLE)"? I will try as soon as I get on my development computer.
  • Agmenor
    Agmenor almost 12 years
    However I type ACCEL_VISIBLE, I always get "NameError: global name 'ACCEL_VISIBLE' is not defined", so I don't know how to include it. If you know a tutorial about my question, it would be very welcome.
  • RobotHumans
    RobotHumans almost 12 years
    The Gtk docs said they moved most constants out of the global namespace. dir(Gtk) from a python shell, copy paste the output in to something where you can search text, oh look the class...dir(Gtk.AccelFlags) and there's VISIBLE. Gtk.AccelFlags.VISIBLE should work fine. The output of print Gtk.AccelFlags.VISIBLE tells you it's the right type.
  • Agmenor
    Agmenor almost 12 years
    Hitting Crtl+b in the running app still does nothing. I had expected it to erase some letters of my entry field? What did I do wrong?
  • 윤이래
    윤이래 over 11 years
    Can this be used to disable Ctrl+F4 shortcut to close the window?
  • Agmenor
    Agmenor over 11 years
    You mean Alt+F4 ? I don't know, I haven't tried.
  • 윤이래
    윤이래 over 11 years
    I meant both Ctrl+F4 and Alt+F4
  • Cameron Laird
    Cameron Laird about 11 years
    Thanks for the reply, i tried that and it comes up with 'Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /volume1/web/phptests/Admin/pro.php on line 20' any suggestions to what i could do?
  • Jonast92
    Jonast92 about 11 years
    Please don't tell people to use the mysqli_query syntax, It's outdated (they dont't service it anymore) and it becomes a real pain in the ass to use once you want to do something really complicated
  • fizzy drink
    fizzy drink about 11 years
    maybe write the full mysql_fetch_array, such as $result = mysql_fetch_array($result, MYSQL_BOTH) or mysql_fetch_array($result, MYSQL_ASSOC)
  • ThorSummoner
    ThorSummoner over 8 years
    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.
  • yPhil
    yPhil almost 8 years
    What is "entry1"?