2017-08-26 129 views
1

我遇到了一個問題,其中wx.EVT_LEFT_UP事件似乎出錯了,或者至少,我覺得它非常違反直覺。wxpython:鼠標事件觸發錯誤

我想在下拉一個面板時按下按鈕,然後在上一個面板上點擊時激活一個功能。

考慮下面的代碼:

import wx 

class Example(wx.Frame): 
    def __init__(self, *args, **kwargs): 
     super(Example, self).__init__(*args, **kwargs) 

     panel = wx.Panel(self) 

     # left panel 
     lPan = wx.Panel(panel) 
     lPan.SetBackgroundColour('#9C4141') 
     lPan.Bind(wx.EVT_LEFT_DOWN, lambda e, p='left': self.onLeftDown(e, p)) 
     lPan.Bind(wx.EVT_LEFT_UP, lambda e, p='left': self.onLeftUp(e, p)) 

     # right panel 
     rPan = wx.Panel(panel) 
     rPan.SetBackgroundColour('#415C9C') 
     rPan.Bind(wx.EVT_LEFT_DOWN, lambda e, p='right': self.onLeftDown(e, p)) 
     rPan.Bind(wx.EVT_LEFT_UP, lambda e, p='right': self.onLeftUp(e, p)) 

     # box sizer 
     hbox = wx.BoxSizer(wx.HORIZONTAL) 
     hbox.Add(lPan, 1, flag=wx.EXPAND) 
     hbox.Add(rPan, 1, flag=wx.EXPAND) 
     panel.SetSizer(hbox) 

     self.Show() 

    def onLeftDown(self, e, panel): 
     print('Mouse down on {} panel'.format(panel)) 

    def onLeftUp(self, e, panel): 
     print('Mouse up on {} panel'.format(panel)) 

if __name__ == '__main__': 
    app = wx.App() 
    Example(None, title='Down and Up click', size=(200, 150)) 
    app.MainLoop() 

這會工作例如使用JavaScript就好了,因爲綁定到事件的Element將獨立地響應Down和Up點擊。然而,在這裏,看起來,Up事件僅針對之前向下點擊的面板激發。 (見圖片)。

enter image description here

正如你所看到的,向上事件被觸發的左側面板,而不是在右側面板中。有沒有人對此有過解釋?

+1

您好,在Windows上,無論在2.7/2.9的wxPython和3.6.2/4.0的wxPython您的例子可以作爲你預計(左下/右上)。您可以使用[WIT](https://wiki.wxpython.org/Widget%20Inspection%20Tool),在進入主循環之前插入雙線,瀏覽面板並激活事件查看器以查看所有事件爲兩個面板實時。 – nepix32

+0

感謝與檢查員的提示。我用它,對我來說,在拖動之後,在右側面板上確實沒有鼠標上移事件(或其他事件,而不是運動和setcursor)。我也使用版本wxPython 4('4.0.0b1 osx-cocoa(phoenix)'),所以它似乎是一個macOS執行錯誤。 – Azial

回答

1

正如nepix32指出的,這可能是一個macOS相關的實現錯誤,所以我嘗試了下面的解決方法。

鼠標進入和離開得到準確檢測,所以我想我綁定這些來跟蹤最新輸入的面板並將其存儲在父級。對於任何面板上的快速點擊,我都可以處理我想要對存儲面板執行的任何操作。

這就是我的意思是(按預期工作):

#!/usr/bin/env python 
import wx 
#import wx.lib.inspection 

class Example(wx.Frame): 
    def __init__(self, *args, **kwargs): 
     super(Example, self).__init__(*args, **kwargs) 

     # parent for left and right panels 
     panel = wx.Panel(self) 
     panel.SetBackgroundColour('#759538') 

     self.lastEntered = None 

     hbox = wx.BoxSizer(wx.HORIZONTAL) 
     # setup some child panels 
     for name in ['left', 'middle', 'right']: 
      pan = wx.Panel(panel, name=name) 
      pan.SetBackgroundColour('#404040') 
      # bind events 
      pan.Bind(wx.EVT_LEFT_DOWN, self.onLeftDown) 
      pan.Bind(wx.EVT_LEFT_UP, self.onLeftUp) 
      pan.Bind(wx.EVT_ENTER_WINDOW, self.onEnter) 
      # put in sizer 
      hbox.Add(pan, 1, flag=wx.EXPAND|wx.ALL, border=5) 

     panel.SetSizer(hbox) 
     self.Show() 

    def onLeftDown(self, e): 
     panel = e.GetEventObject() 
     print('Mouse down on '+panel.GetName()) 

    def onLeftUp(self, e): 
     panel = e.GetEventObject() 
     print('Mouse up on '+panel.GetName()) 
     # the actual up panel 
     if self.lastEntered: 
      print('Actual up on '+self.lastEntered.GetName()) 

    def onEnter(self, e): 
     panel = e.GetEventObject() 
     self.lastEntered = panel 
     print('Entered '+panel.GetName()) 

if __name__ == '__main__': 
    app = wx.App() 
    Example(None, title='Down and Up click', size=(200, 150)) 
    #wx.lib.inspection.InspectionTool().Show() 
    app.MainLoop() 

enter image description here

+0

從我可以確定的情況來看,一旦你點擊了'down',這些事件就被鎖定到被點擊的小部件上,用於'點擊'目的。你是正確的,你會得到'Enter'加'Leave','Motion'等,但鼠標'up'仍然被鎖定到原始鼠標'down'小部件。你可以通過檢查事件的「Id」或「Name」來檢查。您的解決方案適用於2個面板,因爲它可以是或者如果您嘗試爲2個以上的面板實施解決方案,則必須嘗試確定相對於面板位置的光標位置,這可能很複雜。 (Linux的wx 3.0.2.0 gtk2(經典)) –

+0

我編輯了我的答案舉個例子。它適用於多個面板。你可以檢查這是否適用於Linux?我真的需要這個在所有桌面平臺上工作。 – Azial

+0

不,它失敗。進入左側, 鼠標左側向下, 鼠標左側向上, 實際向上左側。 點擊左側並釋放中間 –