2014-02-19 16 views
2

我想在用戶按下OSX上的COMMAND + [任何其他鍵]時捕獲一個事件。由於這些實際上是兩次按鍵,我期望兩個事件:一個是按下COMMAND時,另一個是按下另一個按鍵(不釋放COMMAND鍵)。這適用於除COMMAND以外的每個修飾符,只有第一個事件。爲什麼是這樣的,我該如何解決它?wxPython:在OSX上獲取CMD + [其他鍵]的EVT_KEY_DOWN事件

版本:wxPython3.0-OSX-可可py2.7

示例代碼:

import wx 

def OnKeyDown(e): 
    print "Modifiers: {} Key Code: {}".format(e.GetModifiers(), e.GetKeyCode()) 

app = wx.App() 
frame = wx.Frame(None) 

textctrl = wx.TextCtrl(frame, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.WANTS_CHARS) 
textctrl.Bind(wx.EVT_KEY_DOWN, OnKeyDown) 

frame.Show() 
app.MainLoop() 

對於ALT + d的輸出爲:

Modifiers: 1 Key Code: 307 
Modifiers: 1 Key Code: 68 

對於SHIFT + d輸出是:

Modifiers: 4 Key Code: 306 
Modifiers: 4 Key Code: 68 

只有f或COMMAND + d輸出爲:

Modifiers: 2 Key Code: 308 

感謝您的幫助

附加信息:我使用OSX 10.8 虛擬機上。正如RobinDunn指出的那樣,它可以在他的筆記本電腦上工作。所以很有可能這只是我的環境中的一個問題。 wnnmaw提供了一個很好的解決方法,即使在虛擬環境中也適用於我。

+1

您正在使用什麼版本的OSX的?您是否使用任何非標準的鍵盤映射,IME或處理全局熱鍵的系統插件?我在10.8,我在這裏得到了Cmd + d的關鍵事件。順便說一下,您還應該嘗試使用演示中的KeyEvent示例,以確保它不是被本機窗口小部件竊取的關鍵事件。 – RobinDunn

+0

這絕對是你想用加速器表格解決的問題 – wnnmaw

+0

@RobinDunn:我使用的是10.8,但是我在Windows上的虛擬機上運行它。這可能是原因,即使我仍然持懷疑態度,因爲CMD + d可以在其他非wxpython應用程序中正常工作。我想我需要在真正的蘋果機器上進行進一步測試。 –

回答

0

好的,所以我花了一些時間,但這裏有一個工作代碼塊,可以做你想做的。

需要注意以下幾點:

  • 我這樣做是在Windows上(所以也有一些變化,你可以作出如增加對wx.ACCEL_RAW_CTRL這相當於在Mac上的實際控制鍵,而wx.ACCCEL_CTRL對應支持命令鍵
  • 此代碼絕對可以(而且必須)清理
  • 你必須添加更好的錯誤檢查你把這個給用戶之前

進一步內部消除再見,這裏是

import wx 
from wx.lib.scrolledpanel import ScrolledPanel 

class TestWindow(wx.Frame): 
    def __init__(self): 
     wx.Frame.__init__(self, None, -1, 'Accelerator Table Test', size=(600, 400)) 

     self.panel = ScrolledPanel(parent=self, id=-1) 
     self.panel.SetupScrolling() 

     #Create IDs to be used in initial acclerator table 
     self.functionList = [self.func1, self.func2, self.func3, self.func4, self.func5, self.OnAdd, self.OnDel] 
     self.functionListstr = ["self.func1", "self.func2", "self.func3", "self.func4", "self.func5", "self.OnAdd", "self.OnDel"] 
     self.IDDict = {i: wx.NewId() for i in range(len(self.functionList))} 
     self.IDDictrev = {val:key for key, val in self.IDDict.iteritems()} 

     self.aTableList = [(wx.ACCEL_ALT, ord('S'), self.IDDict[0]),(wx.ACCEL_CTRL, ord('Q'), self.IDDict[1])] 

     #Set up initial accelerator table 
     aTable = wx.AcceleratorTable(self.aTableList) 
     self.SetAcceleratorTable(aTable) 

     #Bind inital accelerator table IDs to functions 
     for i in range(len(self.functionList)): 
      self.Bind(wx.EVT_MENU, self.functionList[i], id=self.IDDict[i]) 


     #Set up control widgets on GUI  
     self.flexgrid = wx.FlexGridSizer(cols=3, hgap=10, vgap=5) 

     cmdkeylbl = wx.StaticText(self.panel, -1, "Command Key") 
     self.cmdkey = wx.ComboBox(self.panel, style=wx.CB_READONLY) 
     cmdkeylist = ["Alt", "Control/Command", "Shift", "OSX Control", "None"] 
     self.cmdkeyconstants = {"Alt":wx.ACCEL_ALT, "Control/Command":wx.ACCEL_CTRL, "Shift":wx.ACCEL_SHIFT, "None":wx.ACCEL_NORMAL} 
     self.cmdkeyconstantsrev = {val:key for key, val in self.cmdkeyconstants.iteritems()} 
     self.cmdkey.SetItems(cmdkeylist) 

     hotkeylbl = wx.StaticText(self.panel, -1, "HotKey (single letter only)") 
     self.hotkey = wx.TextCtrl(self.panel, size=(50,-1)) 

     funclbl = wx.StaticText(self.panel, -1, "Function") 
     self.func = wx.ComboBox(self.panel, style=wx.CB_READONLY) 
     self.func.SetItems(self.functionListstr) 

     self.hbox = wx.BoxSizer(wx.HORIZONTAL) 

     addBtn = wx.Button(self.panel, -1, "Add") 
     delBtn = wx.Button(self.panel, -1, "Delete") 

     self.Bind(wx.EVT_BUTTON, self.OnAdd, addBtn) 
     self.Bind(wx.EVT_BUTTON, self.OnDel, delBtn) 

     self.vbox = wx.BoxSizer(wx.VERTICAL) 

     self.curATable = wx.StaticText(self.panel, -1, self._DisplayATable()) 

     self.flexgrid.Add(cmdkeylbl) 
     self.flexgrid.Add(hotkeylbl) 
     self.flexgrid.Add(funclbl) 
     self.flexgrid.Add(self.cmdkey) 
     self.flexgrid.Add(self.hotkey) 
     self.flexgrid.Add(self.func) 

     self.hbox.Add((20, 20), 0) 
     self.hbox.Add(addBtn) 
     self.hbox.Add((0, 0), 0) 
     self.hbox.Add(delBtn) 
     self.hbox.Add((20, 20), 0) 

     self.vbox.Add(self.flexgrid, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5) 
     self.vbox.Add(self.hbox, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5) 
     self.vbox.Add(self.curATable, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5) 

     self.panel.SetSizer(self.vbox) 
     self.panel.Layout() 

    #Class Functions 
    def _DisplayATable(self): 
     aTablelbl = "" 
     for cmdKey, hotKey, Func in self.aTableList: 
      aTablelbl += "{} + {} calls {}\n".format(self.cmdkeyconstantsrev[cmdKey], chr(hotKey), self.functionListstr[self.IDDictrev[Func]]) 

     return aTablelbl 

    def OnAdd(self, event): 
     self.aTableList.append((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()])) 
     print "Added {} + {} as a shortcut for {}!".format(self.cmdkey.GetValue(), self.hotkey.GetValue()[:1].title(), self.functionListstr[self.func.GetSelection()]) 

     aTable = wx.AcceleratorTable(self.aTableList) 
     self.SetAcceleratorTable(aTable) 
     self.curATable.SetLabel(self._DisplayATable()) 
     self.panel.Layout() 

    def OnDel(self, event): 
     if (self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]) in self.aTableList: 
      self.aTableList.remove((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()])) 

      aTable = wx.AcceleratorTable(self.aTableList) 
      self.SetAcceleratorTable(aTable) 
      self.curATable.SetLabel(self._DisplayATable()) 
      self.panel.Layout() 

     else: 
      dlg = wx.MessageDialog(self, "ERROR: That combination is not in the accelerator table!", "Error", style=wx.OK) 
      dlg.ShowModal() 
      dlg.Destroy() 

    def func1(self, event): 
     dlg = wx.MessageDialog(self, "Func1", "Func1", style=wx.OK) 
     dlg.ShowModal() 
     dlg.Destroy() 

    def func2(self, event): 
     dlg = wx.MessageDialog(self, "Func2", "Func2", style=wx.OK) 
     dlg.ShowModal() 
     dlg.Destroy() 

    def func3(self, event): 
     dlg = wx.MessageDialog(self, "Func3", "Func3", style=wx.OK) 
     dlg.ShowModal() 
     dlg.Destroy() 

    def func4(self, event): 
     dlg = wx.MessageDialog(self, "Func4", "Func4", style=wx.OK) 
     dlg.ShowModal() 
     dlg.Destroy() 

    def func5(self, event): 
     dlg = wx.MessageDialog(self, "Func5", "Func5", style=wx.OK) 
     dlg.ShowModal() 
     dlg.Destroy() 

app = wx.App(False) 
frame = TestWindow() 
frame.Show() 
app.MainLoop() 

希望這是你在找什麼,讓我知道如果您有任何疑問

+0

非常感謝。這不完全是我想要的,但它會做,CMD + x完美。我需要做更多的工作來支持特殊的鍵(例如F1-F12),但是你讓我走上了正確的軌道。 理想情況下,我希望只有一個輸入字段可以捕獲用戶輸入的任何鍵組合(請參見ShortcutEditor)。 –

+0

這應該很容易修改喲得到你想要的。我不知道如何使用F鍵,我會研究它 – wnnmaw

相關問題