pythonwxpythonwxtextctrl

Python TextCtrl search and highlight functionality


I have a TextCtrl which contains various log data, I also have a EditText field whereby the user can search for a string to find, and then click the Find button to locate and highlight the word if it is found in the logs. Your standard Find/highlight in browser/Notepad etc.

The code I have does already work and successfully highlights the user's word, however there are a couple of bits missing that I would like to implement:


Solution

  • All criteria were met: New complete code for wx search and highlight functionality below. It ain't pretty, but it works.

    EDIT: This was solved by adding in a 'Find Next' button with the below code. The count limits the next highlight to 1 word rather than all of them to the end of the data.

    EDIT: solved by creating 2 new global variables that hold the value of old position and length of word, and then recolouring the highlight to black/white before finding new word

    EDIT: solved by resetting the startPos value inside the findTxt def

    global wordPos
    wordPos,oldPos = '',''
    
    #wx widgets
    self.progressBox = wx.TextCtrl(panelLog, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2)
        hBox2.Add(self.progressBox, 5, flag=wx.EXPAND)
        vBox.Add(hBox2, 2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=10)
    
        self.logTxt = wx.TextCtrl(panelLog, style=wx.TE_RICH)
        hBox3.Add(self.logTxt, 1, flag=wx.LEFT, border=5)
    
        self.findBtn = wx.Button(panelLog, -1, "Find")
        self.Bind(wx.EVT_BUTTON, self.findTxt, self.findBtn)
        hBox3.Add(self.findBtn, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=3)
    
        self.findNextBtn = wx.Button(panelLog, -1, "Find Next")
        self.findNextBtn.Disable()
        self.Bind(wx.EVT_BUTTON, self.findNext, self.findNextBtn)
        hBox3.Add(self.findNextBtn, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=3)
        vBox.Add(hBox3, 0, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=10)
    
    #method code
    def findTxt(self,e):
        global wordPos, oldPos
        newstring = self.logTxt.GetValue()
        if wordPos:
            self.progressBox.SetStyle(oldPos, wordPos, wx.TextAttr("black", "white"))
        for i in range(self.progressBox.GetNumberOfLines()):
            line = self.progressBox.GetLineText(i)
            if newstring in line:
                startPos = self.progressBox.GetValue().find(newstring)
                endPos = startPos + len(newstring) 
                wordPos = endPos
                oldPos = startPos
    
                self.progressBox.Bind(wx.EVT_SET_FOCUS, self.highlightText(startPos, endPos))
                startPos = 0
                self.findNextBtn.Enable()
    
    
    def findNext(self,e):
        global wordPos, oldPos
        newstring = self.logTxt.GetValue()
        self.progressBox.SetStyle(oldPos, wordPos, wx.TextAttr("black", "white"))
        count = 0
        for i in range(self.progressBox.GetNumberOfLines()):
            if count == 0: 
                line = self.progressBox.GetValue()
                if newstring in line:
                    startPos = self.progressBox.GetValue().find(newstring, wordPos)
                    endPos = startPos + len(newstring) 
                    wordPos = endPos
                    oldPos = startPos
                    self.progressBox.Bind(wx.EVT_SET_FOCUS, self.highlightText(startPos, endPos))
                    count = 1