How can I add keyboard navigation (using Alt with underlines to suggest what other keys to use) to a python gtk gobject-introspection application.
This code works for showing a simple menu but does not add keyboard navigation:
mb = Gtk.MenuBar()
filemenu = Gtk.Menu()
filem = Gtk.MenuItem()
filem.set_label("File")
filem.set_submenu(filemenu)
closem = Gtk.MenuItem()
closem.show()
closem.set_label("Close")
closem.connect("activate", Gtk.main_quit)
filemenu.append(closem)
mb.append(filem)
How can I change it to allow keyboard navigation?
Set the use-underline property and prepend _ to the key you want to use as shortcut.
close_menu = Gtk.MenuItem()
close_menu.set_label("_Close")
close_menu.set_use_underline(True)
If your version of PyGObject is recent enough, you can also use
close_menu = Gtk.MenuItem("_Close", True)
Related
I would like to create two different menus using Tkinter, one of them is already done
And now I'm trying to create a pop-up menu that opens when I right-click.
Basically, my program is a table tree view with some .txt files, and I want when right-click on either of them to be able to open it in notepad++
This is how I created the first menu:
table_tree = ttk.Treeview(window)
table_tree.grid(column = 0, row = 0, sticky="ns")
# Create menu bar
menubar = Menu(window)
window.config(menu=menubar)
file_menu = Menu(
menubar,
tearoff=0
)
#Then added items...Open/Exit
Then this is how I tried to create the second menu:
def my_popup(e):
right_menu.tk_popup(e.x_window, e.y_window)
#create right click menu
right_menu = Menu(window, tearoff = False)
right_menu.add_command(label = "Open in Notepad", command = open_in_notepad)
window.bind("<Button-3>", my_popup)
open_in_notepad is a function that is getting the path of the file and opens it in notepad.
I even get an error when I right click anywhere: AttributeError: 'Event' object has no attribute 'x_window'. So what I'm trying to do is definitely wrong but I couldn't find a solution until now..
I’m trying to generate a set of menus for a program from a dictionary using a more complex version of the function build_menu below. The function detects what it is supposed to do correctly (detects the structure of submenus and menu entries as desired) but it fails to add them to the window.
Things I have tried:
running the code step by step in a python console - works as intended
storing the menu objects in a global list so they don’t go out of scope in case they get garbage collected - didn’t work
What am I missing?
import tkinter as tk
def not_implemented():
pass
def build_menu(structure_dict, menu):
for entry in structure_dict:
if isinstance(structure_dict[entry], dict):
submenu = tk.Menu(menu, tearoff=False)
build_menu(structure_dict[entry], submenu)
menu.add_cascade(label=entry, menu=submenu)
if callable(structure_dict[entry]):
menu.add_command(label=entry, command=structure_dict[entry])
# format:
# "":{} -> menu or submenu
# "":function -> menu entry
menu_structure = {
"Help": {
"Manual...": not_implemented,
"About...": not_implemented,
}
}
main_window = tk.Tk()
menubar = tk.Menu(main_window)
menubar = build_menu(menu_structure, menubar)
main_window.config(menu=menubar)
main_window.mainloop()
Turns out I am an idiot.
I accidentally assigned build_menu to the variable holding the menu bar.
Correct code near the end is this:
menubar = tk.Menu(main_window)
build_menu(menu_structure, menubar)
main_window.config(menu=menubar)
main_window.mainloop()
I have a wx.menubar in my application, and I want to set focus to it by pressing a key, for example, "alt+o", and have as a result this:
I would like to know if it is possible? or if an event in wxpython to do it exists. Thank you. P.D: I have tried to use the SetFocus () method which extends from wx.Window but it doesn't work
You could use accelerators
For example:
# ...
# Menu Bar
self.menubar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(wx.ID_EXIT, "&Salir", "")
self.menubar.Append(file_menu, "Archiv&o")
self.SetMenuBar(self.menubar)
#...
You should be able to select the "Archivo" menu using "Alt + o".
The problem is simple but i still coudn't figure it out, when i run the code, the Ampersands don't appear in Menu Items. Why?!
I'm using Python 3.7.7 and wxPython 4.1.0, on Thonny v3.2.7.
import wx
def OnQuit(e):
frame.Close()
app = wx.App()
frame = wx.Frame(None, -1, "wxPython Menu")
frame.SetSize(400, 300)
submenu1 = wx.Menu()
submenu1.Append(121, "Import Newsfeed List")
submenu1.Append(122, "Import Bookmarks")
submenu1.Append(123, "Import Mail")
menu1 = wx.Menu()
menu1.Append(10, "Open")
menu1.Append(11, "Save")
menu1.AppendSeparator()
menu1.AppendSubMenu(submenu1, "Import")
menu1.Append(13, "No Exit")
menu2 = wx.Menu()
menu2.Append(20, "Cut")
menu2.Append(21, "Copy")
menu2.Append(22, "Paste")
menu2.Enable(20, False)
menu3 = wx.Menu()
item = wx.MenuItem(menu3, 30, "&Quit\tCtrl+Q")
item.SetBitmap(wx.Bitmap("quit.png"))
menu3.Append(item)
menu3.Bind(wx.EVT_MENU, OnQuit, id = 30)
menuBar = wx.MenuBar()
menuBar.Append(menu1, "&File")
menuBar.Append(menu2, "&Edit")
menuBar.Append(menu3, "&Extras")
frame.SetMenuBar(menuBar)
frame.Centre()
frame.Show()
app.MainLoop()
SetItemLabel(self, label)
Sets the label associated with the menu item.
Note that if the ID of this menu item corresponds to a stock ID, then it is not necessary to specify a label: wxWidgets will automatically use the stock item > label associated with that ID. See the constructor for more info.
The label string for the normal menu items (not separators) may include the
accelerator which can be used to activate the menu item from keyboard. An accelerator key can be specified using the ampersand & character. In order to embed an ampersand character in the menu item text, the ampersand must be doubled. **
https://docs.wxpython.org/wx.MenuItem.html#wx-menuitem
The ampersand (&) is traditionally used as an accelerator on menu items.
If you press the ALT button your menus will (if defined with accelerators i.e. &File where the & next to F means pressing F will open the File menu) display with the accelerator letter underlined.
Press F and the File menu opens.
If menu items in the File menu have accelerators, they too will have a letter underlined, pressing that letter will select that menu item.
If you require an actual ampersand (&) without special meaning e.g. Close & Quit, you need to double the ampersand i.e. the items label should created as Close && Quit or &Close && Quit if the menu should not only display as Close & Quit but also respond when the user presses the letter C.
I'm developing a wxPython GUI, and would like to right-align shortcut text. Obviously one can cludge this using tab characters, but I'd prefer to do it natively if there is a way to.
The default menu item creation is thus:
menu = wx.Menu()
item_id = 1
item_name = 'My menu item'
help_text = 'Clicking this does something interesting.'
item = menu.Append(item_id, item_name, help_text)
I'll be expanding on this with shortcuts, so if I were using tabs, it would be something like:
item_name = 'My menu item\t\tCtrl+Alt+H'
However, that involves a lot of manual \t entries to make sure everything lines up, and anytime a menu item changes name or another item is added, they would all potentially need to be updated. Is there any way around this, e.g. a class method I'm not seeing to automatically associate the keybinding to the menu item?
Edit: I know that when passing text like &My menu item, it does something automatically with the keybinding associated with the ID specified if there is a definition associated with that ID in the accelerators table, correct?
I went digging through a couple other application's code to find the answer. It turns out the default behavior with \t doesn't do what it looks like it would do (i.e. insert a tab character), but is sensibly interpreted by the toolkit as doing precisely what I wanted to do. Thus, the way to right-align a short cut is simple: create it with the text you desire, followed by \t<shortcut> (rather as I had above). In the example code I pasted above, if I wanted my shortcut to be Ctrl + T, it should therefore be thus:
menu = wx.Menu()
item_id = 1
item_name = 'My menu item\tCtrl+T'
help_text = 'Clicking this does something interesting.'
item = menu.Append(item_id, item_name, help_text)
Edit: updated the following section based on Mike Driscoll's very helpful answer.
Note that this creates the shortcut binding (wxPython picks that up), but it doesn't make it selectable using e.g. the Alt key on Windows.
You can associate the Alt key to quickly open the menu and navigate to it by using the ampersand in your item_name text, but you'll still need to associate the desired keybinding manually via the AcceleratorTable:
menu = wx.Menu()
item_id = 1
# Ctrl+T is bound to the keybinding
accelerator_table = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('T'), item_id)])
self.setAcceleratorTable(accelerator_table)
# Ctrl+T is not included, but the menu item can be accessed via Alt key
item_name = '&My menu item'
help_text = 'Clicking this does something interesting.'
item = menu.Append(item_id, item_name, help_text)
This, I imagine, would actually be the preferred pattern, as then anywhere that the item_id was referenced, the shortcut could be referenced automatically. This would also make for seamless updates.
While Chris is right about "\t" indenting the keybinding correctly in the menu, I don't really see what he means by automatically associating anything using an ampersand. The ampersand (&) DOES allow the used to type ALT to get the File menu to open and then if you type another letter that has had the ampersand applied to it, it will jump to that menu item, but the & does not connect the menu item to the accelerator table. That is done via the menu item's ID.
See the following code:
import wx
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")
self.panel = wx.Panel(self, wx.ID_ANY)
menuBar = wx.MenuBar()
fileMenu = wx.Menu()
exitId = wx.NewId()
exitMenuItem = fileMenu.Append(exitId, "&Exit/tCtrl+X",
"Exit the application")
self.Bind(wx.EVT_MENU, self.onExit, id=exitId )
menuBar.Append(fileMenu, "&File")
self.SetMenuBar(menuBar)
accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('X'), exitId )])
self.SetAcceleratorTable(accel_tbl)
#----------------------------------------------------------------------
def onExit(self, event):
""""""
self.Close()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()
Note that the exitId is used to create the menu item, bind the menu item to EVT_MENU and finally, it is used in the AcceleratorTable so the user can use the shortcut key.
Here are a few references that might be helpful:
http://www.blog.pythonlibrary.org/2008/07/02/wxpython-working-with-menus-toolbars-and-accelerators/
http://wiki.wxpython.org/WorkingWithMenus
http://zetcode.com/wxpython/menustoolbars/
http://www.blog.pythonlibrary.org/2010/12/02/wxpython-keyboard-shortcuts-accelerators/