the Mysterious Mouse

Sorry if this is all obvious, but I'm confused: what does happen to a mouse-click in an STC that is within a Frame? Sample code for a test is below.

1. If I just Bind the click in both classes (remove Optional Lines 1 and 2, keep Optional Line 3), and remove the event.Skip() line from both classes' OnMouseDown methods, then the STC gets the click, the Frame doesn't, and a double-click selects text (a whole word) in the STC only intermittently -- whether I can get through depends on chance timing.

2. Restoring an event.Skip() to both mouse methods corrects mouse behavior within the STC. But the Frame still doesn't get the click -- isn't this puzzling?

3. Binding strictly to the STC (uncomment Optional Lines 1 and 3, comment out Optional Line 2), keeping the Skip() lines, makes the click go to both Frame and STC; double-click behavior is normal. Removing the Bind line in the STC makes the click go only to the Frame; double-click still works normally (selecting a word in the STC).

4. If I keep both Bind lines (Optional Lines 1 and 3, not 2). but remove the Skip() line from the STC's method, the click still goes to both, but the double-click behavior is disrupted again. If I restore Skip() to the STC but remove it from the Frame's method, the click goes only to the Frame, and double-click behavior is still irregular. (So I need Skip() in STC for Frame to get the click, and in Frame for the STC to get double-clicks -- I guess this makes sense.)

OK. But a couple of things still puzzle me. First, if both STC and Frame bind the click, with a Skip() in both methods (as in 2 above), why doesn't the click get to the Frame? Second, if I use this line in the Frame
  self.anSTC.Bind( . . . )
the click goes to the Frame, while if I use this in the STC
  self.Bind( . . . )
the click goes to the STC. Apparently, saying "Both these lines bind the event to the STC" is just not accurate. Is one binding to the STC's class and the other to its instance?? I don't think so -- but anyway, how to get from there to this behavior is beyond me.

Charles Hartman
Professor of English, Poet in Residence
Connecticut College
http://cherry.conncoll.edu/cohar
http://villex.blogspot.com

-------------- sample code -------------------------------------
import wx
import wx.stc as stc

class mySTC(stc.StyledTextCtrl):
  def __init__(self, parent, ID):
    stc.StyledTextCtrl.__init__(self, parent, ID)
# Optional Line 1:
# self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
    
  def OnMouseDown(self, event):
    print 'click in STC'
    event.Skip()

class myFrame(wx.Frame):
  def __init__(self, parent, ID, title):
    wx.Frame.__init__(self, parent, ID, title)
    self.anSTC = mySTC(self, -1)
    stcSizer = wx.BoxSizer(wx.HORIZONTAL)
    stcSizer.Add(self.anSTC, 1, wx.EXPAND)
    fSizer = wx.BoxSizer(wx.HORIZONTAL)
    fSizer.Add(stcSizer, 1, wx.EXPAND)
    self.SetAutoLayout(True)
    self.SetSizer(fSizer)
    self.Layout()
# Optional Line 2
# self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
# Optional Line 3
    self.anSTC.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
    
  def OnMouseDown(self, event):
    print 'click in Frame'
    event.Skip()

app = wx.App(redirect=False)
f = myFrame(None, -1, "Mouse Test")
f.Show()
app.MainLoop()

Charles Hartman wrote:

Sorry if this is all obvious, but I'm confused: what does happen to a mouse-click in an STC that is within a Frame? Sample code for a test is below.

1. If I just Bind the click in both classes (remove Optional Lines 1 and 2, keep Optional Line 3), and remove the event.Skip() line from both classes' OnMouseDown methods, then the STC gets the click, the Frame doesn't, and a double-click selects text (a whole word) in the STC only intermittently -- whether I can get through depends on chance timing.

Because without the Skip the STC doesn't get the event, so it is probably only seeing two DCLICK events if you happen to do multiple click events fast enough.

2. Restoring an event.Skip() to both mouse methods corrects mouse behavior within the STC. But the Frame still doesn't get the click -- isn't this puzzling?

No. Non-command events do not propogate up to parent windows.

3. Binding strictly to the STC (uncomment Optional Lines 1 and 3, comment out Optional Line 2), keeping the Skip() lines, makes the click go to both Frame and STC; double-click behavior is normal. Removing the Bind line in the STC makes the click go only to the Frame; double-click still works normally (selecting a word in the STC).

Actually, it *never* goes to the frame. Your optional line 3 is just doing a second binding to the STC but routing it to a method of the frame class.

4. If I keep both Bind lines (Optional Lines 1 and 3, not 2). but remove the Skip() line from the STC's method, the click still goes to both, but the double-click behavior is disrupted again. If I restore Skip() to the STC but remove it from the Frame's method, the click goes only to the Frame, and double-click behavior is still irregular. (So I need Skip() in STC for Frame to get the click, and in Frame for the STC to get double-clicks -- I guess this makes sense.)

Yep. Without the skip then the ProcessEvent function in wxWidgets will stop looking for a matching event handler, so bindings done earlier on the same instance, or event bindings done in base classes will not be called.

OK. But a couple of things still puzzle me. First, if both STC and Frame bind the click, with a Skip() in both methods (as in 2 above), why doesn't the click get to the Frame? Second, if I use this line in the Frame
self.anSTC.Bind( . . . )
the click goes to the Frame, while if I use this in the STC
self.Bind( . . . )
the click goes to the STC. Apparently, saying "Both these lines bind the event to the STC" is just not accurate. Is one binding to the STC's class and the other to its instance?? I don't think so -- but anyway, how to get from there to this behavior is beyond me.

I think all these questions are answered above. Is it clear yet? If not then perhaps some slides from my OSCON presentation may help. Start at slide 38 in http://wxpython.org/OSCON2004/basic/wxPython-OSCON2004.pdf

If you can mentally translate a bit of C++ to Python then this may be helpful too: http://wxwidgets.org/manuals/2.5.3/wx_eventhandlingoverview.html#eventprocessing

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!