clickwxpythonmouseeventtextctrl

searchctrl EVT_LEFT_DOWN event is not working (wxpython)


I tried to make a mouse event with searchctrl, when I click the searchctrl to enter some code. My goal is that when I click the searchctrl(edit to text or wirte), a virtual keyboard(onboard) will start. I found that searchctrl is low category textctrl. but wx.EVT_LEFT_DOWN is not working How can I make it works(I think it is possible. because value=””(hint) is disappear when i click the searchctrl(text)

full code

# -*- coding: utf-8 -*-

import wx

[wxID_FRAME1, wxID_FRAME1TEXTCTRL1,
] = [wx.NewId() for _init_ctrls in range(2)]

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY,
            title = wx.EmptyString, pos = wx.DefaultPosition,
            size = wx.Size( 700,400 ),
          #  style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL
        )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        # Create controls
        sb = wx.StaticBox(self, -1, "Options")
        searchBtnOpt = wx.CheckBox(self, -1, "Search button")
        searchBtnOpt.SetValue(True)
        cancelBtnOpt = wx.CheckBox(self, -1, "Cancel button")
        menuBtnOpt   = wx.CheckBox(self, -1, "Search menu")

        self.search = wx.SearchCtrl(self,size=(200,-1), style=wx.TE_PROCESS_ENTER)
        #self.search.SetHint(self, love)
        # Setup the layout
        self.Bind(wx.EVT_LEFT_DOWN, self.OnClick, self.search)
        box = wx.StaticBoxSizer(sb, wx.VERTICAL)
        box.Add(searchBtnOpt, 0, wx.ALL, 5)
        box.Add(cancelBtnOpt, 0, wx.ALL, 5)
        box.Add(menuBtnOpt,   0, wx.ALL, 5)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(box, 0, wx.ALL, 15)
        sizer.Add((15,15))
        sizer.Add(self.search, 0, wx.ALL, 15)

##         self.tc = wx.TextCtrl(self)  # just for testing that heights match...
##         sizer.Add(self.tc, 0, wx.TOP, 15)

        self.SetSizer(sizer)

        self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
              parent=self, pos=wx.Point(120, 80), size=wx.Size(100, 21),
              style=0, value='textCtrl1')
        self.textCtrl1.Bind(wx.EVT_LEFT_DOWN, self.OnClick)


        # Set event bindings
        self.Bind(wx.EVT_CHECKBOX, self.OnToggleSearchButton, searchBtnOpt)
        self.Bind(wx.EVT_CHECKBOX, self.OnToggleCancelButton, cancelBtnOpt)
        self.Bind(wx.EVT_CHECKBOX, self.OnToggleSearchMenu,   menuBtnOpt)
        self.search.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnSearch, self.search)
        self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel, self.search)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnDoSearch, self.search)
        ##self.Bind(wx.EVT_TEXT, self.OnDoSearch, self.search)


    def OnToggleSearchButton(self, evt):
        self.search.ShowSearchButton( evt.GetInt() )

    def OnToggleCancelButton(self, evt):
        self.search.ShowCancelButton( evt.GetInt() )

    def OnToggleSearchMenu(self, evt):
        if evt.GetInt():
            self.search.SetMenu( self.MakeMenu() )
        else:
            self.search.SetMenu(None)

    def OnClick(self, event):
        print "333"

    def OnSearch(self, evt):
        print "555"

    def OnCancel(self, evt):
        self.log.write("OnCancel")

    def OnDoSearch(self, evt):
        self.log.write("OnDoSearch: " + self.search.GetValue())
        print "555"


    def MakeMenu(self):
        menu = wx.Menu()
        item = menu.Append(-1, "Recent Searches")
        item.Enable(False)
        for txt in [ "You can maintain",
                     "a list of old",
                     "search strings here",
                     "and bind EVT_MENU to",
                     "catch their selections" ]:
            menu.Append(-1, txt)
        return menu
    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def searchCtrlOnSearchButton( self, event ):
        print("SearchCtrl SEARCH_BTN clicked")
        event.Skip()

    def searchCtrlOnTextEnter( self, event ):
        print("SearchCtrl ENTER pressed")
        event.Skip()


if __name__ == '__main__':
    app = wx.PySimpleApp( 0 )
    frame = MyFrame1( None )
    frame.Show()
    app.MainLoop()

This part is the problem

    self.search = wx.SearchCtrl(self,size=(200,-1), style=wx.TE_PROCESS_ENTER)
    self.Bind(wx.EVT_LEFT_DOWN, self.OnClick, self.search)

    self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
          parent=self, pos=wx.Point(120, 80), size=wx.Size(100, 21),
          style=0, value='textCtrl1')
    self.textCtrl1.Bind(wx.EVT_LEFT_DOWN, self.OnClick)

    self.search.Bind(wx.EVT_LEFT_DOWN, self.OnClick)

def OnClick(self, event):
    print "333"

Solution

  • Presumably it is not a good idea from a higher-level-perspective to catch mouse events on a search control but it is better to bind to things as lined out in the documentation (text enter, pressing enter, pressing search/clear button, ...).

    This said, I used the wxPython WIT (widget inspection Tool) to get a visualization what is going on. It is activated by adding the following before your main loop:

        ...
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    
        app.MainLoop()
    

    If you browse the widget tree in the left pane, you can see that SearchCtrl has a TextCtrl as it's child, named text. If you further click on the TextCtrl in the widget tree and activate the Event window in the toolbar, you see that it is getting all the wx.EVT_LEFT_DOWN events. I do not know why the search control does not inherit the mouse events from the text control. It receives EVT_TEXT! You can do as follows:

        self.search = wx.SearchCtrl(#...
    
        search_txtctrl = self.search.FindWindowByName('text')
        search_txtctrl.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
    
    def OnClick(self, evt)
        # do your stuff
        evt.Skip()
    

    Do not forget to skip at this point, otherwise the wx.TextCtrl in the search control will not receive any mouse down events!