2012-12-03 61 views
0

我有一個應用程序,允許一些控制器更改主菜單欄的佈局。我通過將主菜單欄傳遞給控制器​​來完成此操作,然後控制器向其添加一些菜單。我的問題是綁定菜單點擊事件添加到這些菜單。這很容易在理論:爲什麼我不能直接將事件綁定到Windows中的wx.Menu?

def bind_main_menu_bar(self, main_menu_bar): 
    self.main_menu_bar = main_menu_bar 

    edit_menu = shared.create_menu([ 
     (const.ID_UNDO, self.LABEL_UNDO_EMPTY), 
     (const.ID_REDO, self.LABEL_REDO_EMPTY), 
     (), 
     (const.ID_VALIDATE_ADDRESSES, 'Validate selected addresses'), 
     (const.ID_VALIDATE_ALL_ADDRESSES, 'Validate all addresses'), 
    ]) 
    edit_menu.Bind(wx.EVT_MENU, self.on_menu) 
    edit_menu.Bind(wx.EVT_UPDATE_UI, self.on_menu_update) 

    main_menu_bar.Insert(1, edit_menu, 'Edit') 

這工作出色在OSX,但在Windows中,只有wx.EVT_MENU事件直接綁定事件到edit_menu菜單時的作品。換句話說,不會觸發wx.EVT_UPDATE_UI事件處理程序。我也試過綁定EVT_MENU_OPEN,EVT_MENU_CLOSEEVT_MENU_HIGHLIGHT,但沒有一個能夠工作。當我將它們綁定到頂層框架時,它們都可以工作,但是無法將事件處理程序僅限於edit_menu菜單。

這是一個錯誤,還是有我忽略的東西?另外,任何人都可以針對我的問題找到解決方法嗎?


我在窗口8.

+0

什麼是'shared.create_menu'?你能分享一下代碼,或者說清楚你指的是哪個內置函數嗎?! –

回答

4

邁克的權利,避免明確的ID - 你不需要他們(詳情請見wxPython Style guide in the wiki)。

菜單項不是常規的Windows,所以你不能對它們做正常的事件綁定的事情 - 太糟糕了。

但是,當您將事件綁定到框架時,您可以指定事件來自哪裏。我綁定菜單事件通常成語:

FileMenu = wx.Menu() 
item = FileMenu.Append(wx.ID_EXIT, "&Quit") 
self.Bind(wx.EVT_MENU, self.OnQuit, item) 

在這種情況下,selfFrame - 所以你說:綁定EVT_MENU的框架,叫self.OnQuit的回調,但只有綁定從這個事件特定的菜單項。

這是醜陋的,當你做動態綁定,但它應該工作。

注意,在這個例子中,我使用的ID - 異常到規則是,使用標準的ID(如wx.ID-EXITwx.ID_HELP)是不錯的,因爲那時wx可以「做正確的事」在各種平臺上(如更多OS-X上的應用程序菜單的相當菜單)。

+0

+1我沒有認真考慮綁定一個單獨的處理程序到每個菜單項。看起來它可能是最好的解決方案。對於我來說,創造一大堆只用於菜單項目的小三行方法似乎非常浪費。太糟糕了,我不能指定'wx.Menu'作爲事件源。 – Hubro

1

使用wxPython的2.9(DEV)我敢肯定,你應該菜單事件綁定到框架,而不是菜單項本身。試試看看它是否有效。

+0

是的,正如我在我的問題中所說的:「當我將它們綁定到頂層框架時,它們都可以工作,但是無法將事件處理程序僅限制在'edit_menu'菜單中。」我直接將事件綁定到編輯菜單比將它們綁定到頂層框架更容易和簡單,因爲我必須小心處理程序之間沒有菜單按鈕ID衝突,並且我有記得在我最終刪除編輯菜單時解除綁定的所有事件。 – Hubro

+0

那麼你不應該在wx中使用硬編碼的ID。使用wx.NewId或wx.ID_ANY –

+0

我爲所有的ID使用'wx.NewId',但給了足夠的菜單項,我可以很容易地想象一個編輯器菜單中的項目ID與一個ID項目在基本菜單中。我使用ID IDUNDO和ID_VALIDATE_ADDRESSES等ID名稱,而不是爲每個項目創建一個新的ID。 – Hubro

相關問題