Hi all,
first time post. I am creating a WX program and having issues with showing the panels. The issues I am having:
- Ctrl+tab does not switch between panels and set the keyboard focus to the first child control of the panel.
- When using alt+1, alt+2 or alt+3 or via the menu window. The panel is not being displayed. You get a blank screen. when the progrma launches, Panel1 is shown fine.
- When I switch to another program and back to the Wx program. Keyboard focus is not on the last control with keyboard focus.
- This program is being design to support keyboard and screen reader users.
Below is the frame class in full. Let me know if you require the panel classes.
class MyFrame(wx.MDIParentFrame):
def init(self):
wx.MDIParentFrame.init(self, None, title=“Library”)
self.panel1 = EditPanel(self, self)
self.panel2 = RecordListPanel(self)
self.panel3 = RecordPanel(self, self)
self.panel1.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.panel2.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.panel3.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.panel1.Show()
self.SetMenuBar(self.create_menubar())
self.SetupShortcutKeys()
self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
#self.SetSize((1920, 1080))
self.Maximize()
self.Center()
# Set focus on child edit object of Panel1
self.panel1.edit.SetFocus()
self.last_focus_id = None # variable to store the ID of the control with focus
def onTab(self, event):
current_panel = self.GetActiveChild()
if current_panel is None:
current_panel = self.GetChildren()[0]
panel = event.GetEventObject()
panels = self.GetChildren()
if wx.GetKeyState(wx.WXK_CONTROL):
if wx.GetKeyState(wx.WXK_SHIFT):
previous_panel = current_panel.GetPrevSibling()
if previous_panel:
if previous_panel== panels[1]:
# skip the status bar panel. Need to find a method of removing the status bar from the windowList object. Currently defined in the EditPanel class.
previous_panel = panels[0]
self.switchPanel(previous_panel)
else:
self.switchPanel(panels[0]) # first panel.
else:
next_panel = current_panel.GetNextSibling()
if next_panel:
if next_panel == panels[1]:
next_panel = panels[2]
self.switchPanel(next_panel)
else:
self.switchPanel(panels[-1])
def OnSetFocus(self, event):
print ("OnSetFocus method")
event.Skip()
self.SetTitle(event.GetEventObject().GetParent().GetTitle())
event.GetEventObject().GetChildren()[0].SetFocus()
# save the ID of the control with focus
self.last_focus_id = event.GetId()
def OnChildFocus(self, event):
print ("OnChildFocus method")
children = event.GetWindow().GetChildren()
if children:
children[0].SetFocus()
# save the ID of the control with focus
self.last_focus_id = event.GetId()
def switchPanel(self, panel):
print (f"switch panel {panel}")
current_panel = self.GetActiveChild()
#current_panel = self.GetActiveChild()
if current_panel is None:
current_panel = self.GetChildren()[0]
#if current_panel:
#if current_panel.GetNextSibling() == panel:
#print ("getting next sibling ")
#self.ActivateNext()
#elif current_panel.GetPrevSibling() == panel:
#print ("getting prior control")
#self.ActivatePrevious()
#else:
#print ("hiding current panel")
current_panel.Hide()
# restore the focus state of the window
#if self.last_focus_id:
#control = wx.FindWindowById(self.last_focus_id)
#if control:
#control.SetFocus()
print ("showing and focusing on panel")
#panel.SetFocus()
if panel is self.panel1:
print ("panel1 has focus")
self.panel1.edit.SetFocus()
elif panel is self.panel2:
self.panel2.list_ctrl.SetFocus()
elif panel is self.panel3:
self.panel3.title_text.SetFocus()
def on_exit(self, event):
self.Close()
def create_menubar(self):
self.menubar = wx.MenuBar()
# Create the "Options" menu
self.options_menu = wx.Menu()
self.save_record_item = self.options_menu.Append(wx.ID_ANY, "Save Record\tCtrl+S", "Save to database")
self.Bind(wx.EVT_MENU,self.panel1.saveDb, self.save_record_item)
self.next_file_item = self.options_menu.Append(wx.ID_ANY, "Next file\tCtrl+N", "Load next file")
self.prior_file_item = self.options_menu.Append(wx.ID_ANY, "Prior file\tCtrl+P", "Load prior file")
self.review_record_item = self.options_menu.Append(wx.ID_ANY, "Review Record\tCtrl+r", "Review record")
self.Bind(wx.EVT_MENU,self.panel1.ShowMemoryRecord, self.review_record_item)
self.Bind(wx.EVT_MENU,self.panel1.nextBook, self.next_file_item)
self.Bind(wx.EVT_MENU,self.panel1.priorBook, self.prior_file_item)
self.clear_record_item = self.options_menu.Append(wx.ID_ANY, "Clear Record\Alt+I", "Clear record in memory")
self.Bind(wx.EVT_MENU,self.panel1.clearRecord, self.clear_record_item)
self.exit_item = self.options_menu.Append(wx.ID_EXIT, "Exit", "Exit the program")
self.Bind(wx.EVT_MENU, self.on_exit, self.exit_item)
self.menubar.Append(self.options_menu, "&Options")
# Create the "Save to record" menu
self.save_menu = wx.Menu()
self.title_item = self.save_menu.Append(wx.ID_ANY, "Title\tAlt+T", "Save book title")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.TITLE.value), self.title_item)
self.author_item = self.save_menu.Append(wx.ID_ANY, "Author\tAlt+A", "Save book author")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateListMemoryField(FieldNames.AUTHORS.value), self.author_item)
self.series_item = self.save_menu.Append(wx.ID_ANY, "Series\tAlt+S", "Save book Series")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.SERIES.value), self.series_item)
self.seriesNo_item = self.save_menu.Append(wx.ID_ANY, "SeriesNo\tCtrl+3", "Save Series No")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.SERIES_NO.value), self.seriesNo_item)
self.genre_item = self.save_menu.Append(wx.ID_ANY, "Genre\tAlt+G", "Save book genre")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateListMemoryField(FieldNames.GENRES.value), self.genre_item)
self.description_item = self.save_menu.Append(wx.ID_ANY, "Description\tAlt+D", "Save book description")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.DESCRIPTION.value), self.description_item)
self.aboutAuthor_item = self.save_menu.Append(wx.ID_ANY, "About Author\tAlt+B", "Save about author")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.UpdateAboutAuthor(FieldNames.AUTHORS.value), self.aboutAuthor_item)
self.narrator_item = self.save_menu.Append(wx.ID_ANY, "Narrator\tAlt+N", "Save book narrator")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateListMemoryField(FieldNames.NARRATORS.value), self.narrator_item)
self.release_item = self.save_menu.Append(wx.ID_ANY, "Release Date\tAlt+R", "Save book release date")
self.Bind(wx.EVT_MENU,lambda event: self.panel1.updateMemoryField(FieldNames.RELEASE.value), self.release_item)
self.duration_item = self.save_menu.Append(wx.ID_ANY, "Duration\tCtrl+D", "Save book duration")
self.Bind(wx.EVT_MENU,lambda event: self.panel1.updateMemoryField(FieldNames.DURATION.value), self.duration_item)
self.copyright_item = self.save_menu.Append(wx.ID_ANY, "Copyright\tAlt+C", "Save book copyright")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.COPYRIGHT.value), self.copyright_item)
self.publisher_item = self.save_menu.Append(wx.ID_ANY, "Publisher\tAlt+P", "Save book publisher")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.PUBLISHER.value), self.publisher_item)
self.misc_item = self.save_menu.Append(wx.ID_ANY, "Misc\tAlt+M", "Save book misc")
self.Bind(wx.EVT_MENU, lambda event: self.panel1.updateMemoryField(FieldNames.MISC.value), self.misc_item)
self.menubar.Append(self.save_menu, "Sa&ve to record")
# Create the "Windows" menu
self.windows_menu = wx.Menu()
self.switch_panel1_item = self.windows_menu.Append(wx.ID_ANY, "Switch to Edit Panel\tAlt+1", "Switch to the edit panel")
self.Bind(wx.EVT_MENU, lambda event: self.switchPanel(self.panel1), self.switch_panel1_item)
self.switch_panel2_item = self.windows_menu.Append(wx.ID_ANY, "Switch to Record List Panel\tAlt+2", "Switch to the record list panel")
self.Bind(wx.EVT_MENU, lambda event: self.switchPanel(self.panel2), self.switch_panel2_item)
self.switch_panel3_item = self.windows_menu.Append(wx.ID_ANY, "Switch to Record Panel\tAlt+3", "Switch to the record panel")
self.Bind(wx.EVT_MENU, lambda event: self.switchPanel(self.panel3), self.switch_panel3_item)
self.menubar.Append(self.windows_menu, "&Windows")
self.SetMenuBar(self.menubar)
def SetupShortcutKeys (self):
self.tab_id = wx.NewIdRef()
# Set up the accelerator table
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('S'), self.save_record_item.GetId()),
(wx.ACCEL_CTRL, ord('N'), self.next_file_item.GetId()),
(wx.ACCEL_CTRL, ord('P'), self.prior_file_item.GetId()),
(wx.ACCEL_CTRL, ord('R'), self.review_record_item.GetId()),
(wx.ACCEL_ALT, ord('I'), self.clear_record_item.GetId()),
(wx.ACCEL_ALT, ord('T'), self.title_item.GetId()),
(wx.ACCEL_ALT, ord('A'), self.author_item.GetId()),
(wx.ACCEL_ALT, ord('S'), self.series_item.GetId()),
(wx.ACCEL_CTRL, ord('3'), self.seriesNo_item.GetId()),
(wx.ACCEL_ALT, ord('G'), self.genre_item.GetId()),
(wx.ACCEL_ALT, ord('D'), self.description_item.GetId()),
(wx.ACCEL_ALT, ord('B'), self.aboutAuthor_item.GetId()),
(wx.ACCEL_ALT, ord('N'), self.narrator_item.GetId()),
(wx.ACCEL_ALT, ord('R'), self.release_item.GetId()),
(wx.ACCEL_CTRL, ord('D'), self.duration_item.GetId()),
(wx.ACCEL_ALT, ord('C'), self.copyright_item.GetId()),
(wx.ACCEL_ALT, ord('P'), self.publisher_item.GetId()),
(wx.ACCEL_ALT, ord('M'), self.misc_item.GetId()),
(wx.ACCEL_ALT, ord('1'), self.switch_panel1_item.GetId()),
(wx.ACCEL_ALT, ord('2'), self.switch_panel2_item.GetId()),
(wx.ACCEL_ALT, ord('3'), self.switch_panel3_item.GetId()),
(wx.ACCEL_CTRL, wx.WXK_TAB, self.tab_id),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, wx.WXK_TAB, self.tab_id)
])
self.SetAcceleratorTable(self.accel_tbl)
self.Bind(wx.EVT_MENU, self.onTab, id=self.tab_id)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame()
self.frame.Show(True)
return True
if name == ‘main’:
app = MyApp(0, True)
app.MainLoop()
Any tips or ways of improving the keyboard focus management are welcomed.