Trying to add hotkeys to menu items?

Yes, most of the code is generated by WXGlide, but I’m trying to add in hotkey support for the Menu Items…
(eg. Keyboard-left arrow for previous, Keyboard-right arrow for next).

I’ve Binded self.Bind(wx.EVT_CHAR_HOOK, self.on_key), which my understand is should cause every Character to be sent to that function. But it’s not working.

Can anyone point me in the right direction (and I’m also surprised that this functionality isn’t in WxGlide? Did I miss it)

    - Ben
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 0.9.5 on Mon Jun  8 14:22:22 2020
#

import wx

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        ## Insert Before

        # Menu Bar
        self.frame_menubar = wx.MenuBar()
        wxglade_tmp_menu = wx.Menu()
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Open File", "")
        self.Bind(wx.EVT_MENU, self.OpenFile, id=item.GetId())
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Close File", "")
        self.Bind(wx.EVT_MENU, self.CloseFile, id=item.GetId())
        self.frame_menubar.Append(wxglade_tmp_menu, "File")
        wxglade_tmp_menu = wx.Menu()
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Next Page", "")
        self.Bind(wx.EVT_MENU, self.GoNextPage, id=item.GetId())
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Previous Page", "")
        self.Bind(wx.EVT_MENU, self.GoPreviousPage, id=item.GetId())
        wxglade_tmp_menu.AppendSeparator()
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Jump to 1st Page", "")
        self.Bind(wx.EVT_MENU, self.GoFirstPage, id=item.GetId())
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Jump to Last Page", "")
        self.Bind(wx.EVT_MENU, self.GoLastPage, id=item.GetId())
        wxglade_tmp_menu.AppendSeparator()
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Skip Forward 10 Pages", "")
        self.Bind(wx.EVT_MENU, self.Go10Ahead, id=item.GetId())
        item = wxglade_tmp_menu.Append(wx.ID_ANY, "Skip Back 10 Pages", "")
        self.Bind(wx.EVT_MENU, self.Go10Back, id=item.GetId())
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(wx.ID_ANY, "item", "")
        self.frame_menubar.Append(wxglade_tmp_menu, "Go")
        self.SetMenuBar(self.frame_menubar)
        # Menu Bar end
        ## Insert After

        self.Bind(wx.EVT_LEFT_DOWN, self.GoPreviousPage)
        self.Bind(wx.EVT_RIGHT_DOWN, self.GoNextPage)
        self.Bind(wx.EVT_CHAR_HOOK, self.on_key)
        self.frame_statusbar = self.CreateStatusBar(1)

        self.__set_properties()
        self.__do_layout()

        # end wxGlade

    ## extra code
    def on_key(self, event):
        print("on key")
        key = event.GetKeyCode()
        if key == wx.WXK_DOWN:
            self.GoPreviousPage()
        elif key == wx.WXK_UP:
            self.GoNextPage()
        else:
            event.Skip()

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("frame")
        self.frame_statusbar.SetStatusWidths([-1])

        # statusbar fields
        frame_statusbar_fields = ["frame_statusbar"]
        for i in range(len(frame_statusbar_fields)):
            self.frame_statusbar.SetStatusText(frame_statusbar_fields[i], i)
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        bitmap_1 = wx.StaticBitmap(self, wx.ID_ANY, wx.NullBitmap, style=wx.FULL_REPAINT_ON_RESIZE)
        sizer_1.Add(bitmap_1, 0, wx.ALL | wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

    def OpenFile(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'OpenFile' not implemented!")
        event.Skip()

    def CloseFile(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'CloseFile' not implemented!")
        event.Skip()

    def GoNextPage(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'GoNextPage' not implemented!")
        event.Skip()

    def GoPreviousPage(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'GoPreviousPage' not implemented!")
        event.Skip()

    def GoFirstPage(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'GoFirstPage' not implemented!")
        event.Skip()

    def GoLastPage(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'GoLastPage' not implemented!")
        event.Skip()

    def Go10Ahead(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'Go10Ahead' not implemented!")
        event.Skip()

    def Go10Back(self, event):  # wxGlade: MyFrame.<event_handler>
        print("Event handler 'Go10Back' not implemented!")
        event.Skip()

# end of class MyFrame

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

# end of class MyApp

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

Search this forum for howto’s and a more manual approach before trying wxGlade. When you get to grips with manual coding first, you will understand and appreciate the generated code more.

Good luck and take your time reading, coding, trying, erring and learning.

Typically, the wx.EVT_CHAR_HOOK is only used as a last resort. Depending on the types of widgets and where the keyboard focus is at currently, then wx.EVT_CHAR_HOOK may not even get a chance to be sent. I think it is failing in your example because the frame is not able to have the keyboard focus for itself, and its only child is a static bitmap, so it can’t have the focus either.

You can add accelerators to menu items simply by adding a tab character followed by the key name to the menu item’s label. Like "Open\tCtrl-O" You can also get menu events for keys that don’t have a menu item by using an wx.AcceleratorTable, See: https://docs.wxpython.org/wx.AcceleratorTable.html

1 Like