How do I create and use keyboard shortcuts in a Gtk app that I am developing?
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.
Related videos on Youtube
Cameron Laird
Updated on September 18, 2022Comments
-
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 over 4 yearsThe first link is broken...
-
-
Agmenor almost 12 yearsThank 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 almost 12 yearsIt'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 almost 12 yearsRight, you need to create accelerators yourself; I've updated the example to show how.
-
Agmenor almost 12 yearsAfter 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 almost 12 yearsI 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 almost 12 yearsHowever 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 almost 12 yearsThe 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 almost 12 yearsHitting 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 yearsCan this be used to disable Ctrl+F4 shortcut to close the window?
-
Agmenor over 11 yearsYou mean Alt+F4 ? I don't know, I haven't tried.
-
윤이래 over 11 yearsI meant both Ctrl+F4 and Alt+F4
-
Cameron Laird about 11 yearsThanks 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 about 11 yearsPlease 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 about 11 yearsmaybe write the full mysql_fetch_array, such as $result = mysql_fetch_array($result, MYSQL_BOTH) or mysql_fetch_array($result, MYSQL_ASSOC)
-
ThorSummoner over 8 yearsSo I noticed; when using
clicked
the accelerator can be mashed very quickly, but the button doesn't visually depress. When usingactivate
, the button will depress, but the accelerator can only be pressed once the visual depress is finished. -
yPhil almost 8 yearsWhat is "entry1"?