How can I use Keyboard Shortcuts in WxPython?

Hi,
Well, I have a simple text editor in WxPython.
So, I wish I could call File/Open for CTRL+o, File/Save for CTRL+s, File/Save as for CTRL+Shift+s. And in addition, I need some other keys Keyboard Shortcuts.
Well, I’ve tried Keyboard Shortcuts (Accelerators), but it doesn’t work.
Can someone help me please?

import os
import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(800,600))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar()
        filemenu = wx.Menu()
        menuOpen = filemenu.Append(wx.ID_OPEN, "&Open"," Open a file")
        menuSave = filemenu.Append(wx.ID_SAVE, "&Save"," Save a file")
        menuSaveAs = filemenu.Append(wx.ID_SAVEAS, "&Save as"," Save a file as")
        menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File")
        self.SetMenuBar(menuBar)
        self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
        self.Bind(wx.EVT_MENU, self.OnSave, menuSave)
        self.Bind(wx.EVT_MENU, self.OnSaveAs, menuSaveAs)
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
        exit_id = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnKeyExit, id=exit_id)
        a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('Q'), exit_id )])
        self.SetAcceleratorTable(a_tbl)
        self.Show(True)
...
    def onKeyExit(self, e):
            self.Close()
app = wx.App(False)
frame = MainWindow(None, "Test")
app.MainLoop()

Hi Jonikster,

When posting code samples please enclose them in the correct tags, otherwise the site’s software will translate things like double-underscores as bold, convert single and double-quotes to versions that are invalid in real code and also completely wreck the indentation.

The problem with your example is that it binds to self.OnKeyExit but defines onKeyExit() which is not the same.

One of the advantages of using an IDE such as PyCharm is that it would automatically highlight self.OnKeyExit as being undefined.

Also wx.NewId() is deprecated, use wx.NewIdRef() instead.

I reduced your code and fixed the onKeyExit vs. OnKeyExit bug, and got this, which works for me:

import os
import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(800,600))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar()
        filemenu = wx.Menu()
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File")
        self.SetMenuBar(menuBar)
        self.Bind(wx.EVT_MENU, self.onKeyExit, menuExit)
        exit_id = wx.NewIdRef()
        self.Bind(wx.EVT_MENU, self.onKeyExit, id=exit_id)
        a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('Q'), exit_id )])
        self.SetAcceleratorTable(a_tbl)
        self.Show(True)

    def onKeyExit(self, e):
        self.Close()

app = wx.App(False)
frame = MainWindow(None, "Test")
app.MainLoop()

In my code I have self.OnKeyExit and def OnKeyExit.

I have the same code and it works without errors. But when I press CTRL+Q, nothing happens.

I don’t know what I did, but it works now.
And I have another problem.
So I need to use ctrl+1, ctrl+2, ctrl+3, ctrl+4 on the main keyboard in my program.
This code is not working:

record_id = wx.NewIdRef()
stop_id = wx.NewIdRef()
play_id = wx.NewIdRef()
delete_id = wx.NewIdRef()
self.Bind(wx.EVT_MENU, self.OnKeyRecord, id=record_id)
self.Bind(wx.EVT_MENU, self.OnKeyStop, id=stop_id)
self.Bind(wx.EVT_MENU, self.OnKeyPlay, id=play_id)
self.Bind(wx.EVT_MENU, self.OnKeyDelete, id=delete_id)
a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord(‘1’), record_id )])
a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord(‘2’), stop_id )])
a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord(‘3’), play_id )])
a_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord(‘4’), delete_id )])
self.SetAcceleratorTable(a_tbl)
def OnKeyRecord(self, e):

def OnKeyStop(self, e):

def OnKeyPlay(self, e):

def OnKeyDelete(self, e):

I pressed, nothing happened.

What your code is doing is creating a number of accelerator tables containing just one accelerator entry and assigning each table to the same variable ‘a_tbl’. This results in only the last table being set.

Have a look at the following page for examples of how to add multiple accelerator entries to an accelerator table: