创建多个 wx.AcceleratorEntry() 条目并将函数绑定到它们的正确方法是什么? wxPython
What is the right way to create multiple wx.AcceleratorEntry() entries and bind functions to them? wxPython
目前我正在做我的 wxPython 高中期末项目,我正面临另一个问题
我想将按键组合条目(例如CTRL+S...)绑定到我的功能,但我无法达到我期望的结果。
这个我试过了,但是按键没有绑定。
accelnum = 2
accelerators = [wx.AcceleratorEntry() for x in range(accelnum)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), 'save')
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), 'export')
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
def save(self, event):
# some code...
def export(self, event):
# some other code...
我也尝试将 ID 设置为与我设置工具栏工具相同的 ID,但它说
'id' 在这里不是有效参数。
非常感谢您的所有建议。 R
编辑
对于所有想知道可能有什么问题的人,我还使用 wx.EVT_CHAR_HOOK 来检测 "DEL" 键。当我第二次重写我的 class 时,我忘记添加 EVT_CHAR_HOOK 并且它起作用了。直到我添加 EVT_CHAR_HOOK 回来。这意味着您不能同时使用它。所以我接下来做了什么:
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
ID_DELETE = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(3)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
accelerators[2].Set(wx.ACCEL_NORMAL, wx.WXK_DELETE, ID_DELETE)
同时分配我的删除按钮,现在可以使用了
参见:https://docs.wxpython.org/wx.AcceleratorEntry.html#wx.AcceleratorEntry.Set
Set
的第三个参数应该是创建和发送事件时要使用的 ID。所以你会想这样做:
ID_SAVE = wx.NewIdRef()
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
当按下该键时,将发送一个 EVT_MENU
事件,因此您还需要为其绑定一个处理程序,如下所示:
self.Bind(wx.EVT_MENU, self.save, id=ID_SAVE)
Robin 的回答一如既往地有效。
您可能希望检查一下您是如何实施它的。
尝试这样的事情:
import wx
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(2)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="", size=(360,100)):
super(MyFrame, self).__init__(parent, id, title, size)
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
self.panel = wx.Panel(self)
self.Bind(wx.EVT_MENU, self.OnSave, id=ID_SAVE)
self.Bind(wx.EVT_MENU, self.OnExport, id=ID_EXPORT)
self.Show()
def OnSave(self, event):
print("Save")
event.Skip()
def OnExport(self, event):
print("Export")
event.Skip()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None,title="An Accelerator Test")
app.MainLoop()
其他答案已经解释了'how to'。也许这个例子可以让新读者更容易编码。
正如您在其他答案中所读到的,创建加速器需要 3 个步骤:1) 创建一个 id,2) 创建一个加速器,以及 3) 绑定到 EVT_MENU。我自己花了一些时间让它工作。
所以在 'getting the right way' 之后,我创建了一种让我更容易的方法,“更简单的方法”,当使用很多加速器时,通过将它们定义在一个中地方。
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
然后让python做无聊的事情。
# ------------------------------------------------------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
一个完整的工作示例。
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Accelerator Test", size=(500, 500))
panel = wx.Panel(self, wx.ID_ANY)
# define the accelerators ---------------------------------------------
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
# create the accelerators ---------------------------
self._create_accelerators()
# ----------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
# -------------------------------------------------------------------------------
def on_previous(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_next(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_select_all(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# ===================================================================================
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
一些输出。
You pressed Next Page (PageDown)
You pressed Previous Page (PageUp)
You pressed Select All (Ctrl+A)
目前我正在做我的 wxPython 高中期末项目,我正面临另一个问题 我想将按键组合条目(例如CTRL+S...)绑定到我的功能,但我无法达到我期望的结果。
这个我试过了,但是按键没有绑定。
accelnum = 2
accelerators = [wx.AcceleratorEntry() for x in range(accelnum)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), 'save')
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), 'export')
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
def save(self, event):
# some code...
def export(self, event):
# some other code...
我也尝试将 ID 设置为与我设置工具栏工具相同的 ID,但它说 'id' 在这里不是有效参数。
非常感谢您的所有建议。 R
编辑
对于所有想知道可能有什么问题的人,我还使用 wx.EVT_CHAR_HOOK 来检测 "DEL" 键。当我第二次重写我的 class 时,我忘记添加 EVT_CHAR_HOOK 并且它起作用了。直到我添加 EVT_CHAR_HOOK 回来。这意味着您不能同时使用它。所以我接下来做了什么:
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
ID_DELETE = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(3)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
accelerators[2].Set(wx.ACCEL_NORMAL, wx.WXK_DELETE, ID_DELETE)
同时分配我的删除按钮,现在可以使用了
参见:https://docs.wxpython.org/wx.AcceleratorEntry.html#wx.AcceleratorEntry.Set
Set
的第三个参数应该是创建和发送事件时要使用的 ID。所以你会想这样做:
ID_SAVE = wx.NewIdRef()
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
当按下该键时,将发送一个 EVT_MENU
事件,因此您还需要为其绑定一个处理程序,如下所示:
self.Bind(wx.EVT_MENU, self.save, id=ID_SAVE)
Robin 的回答一如既往地有效。
您可能希望检查一下您是如何实施它的。
尝试这样的事情:
import wx
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(2)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="", size=(360,100)):
super(MyFrame, self).__init__(parent, id, title, size)
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
self.panel = wx.Panel(self)
self.Bind(wx.EVT_MENU, self.OnSave, id=ID_SAVE)
self.Bind(wx.EVT_MENU, self.OnExport, id=ID_EXPORT)
self.Show()
def OnSave(self, event):
print("Save")
event.Skip()
def OnExport(self, event):
print("Export")
event.Skip()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None,title="An Accelerator Test")
app.MainLoop()
其他答案已经解释了'how to'。也许这个例子可以让新读者更容易编码。
正如您在其他答案中所读到的,创建加速器需要 3 个步骤:1) 创建一个 id,2) 创建一个加速器,以及 3) 绑定到 EVT_MENU。我自己花了一些时间让它工作。
所以在 'getting the right way' 之后,我创建了一种让我更容易的方法,“更简单的方法”,当使用很多加速器时,通过将它们定义在一个中地方。
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
然后让python做无聊的事情。
# ------------------------------------------------------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
一个完整的工作示例。
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Accelerator Test", size=(500, 500))
panel = wx.Panel(self, wx.ID_ANY)
# define the accelerators ---------------------------------------------
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
# create the accelerators ---------------------------
self._create_accelerators()
# ----------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
# -------------------------------------------------------------------------------
def on_previous(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_next(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_select_all(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# ===================================================================================
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
一些输出。
You pressed Next Page (PageDown)
You pressed Previous Page (PageUp)
You pressed Select All (Ctrl+A)