1

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:

  • The ability to search the same word, and have the next word highlighted e.g a 'Find Next' 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 log.
  • Un-highlight the current word when a new word is searched, be it the same word, or a new word
  • Start the position at 0 (top of the data) if searching a new word EDIT: solved by resetting the startPos value inside the findTxt def

    def findTxt(self,e):
    global wordPos
    newstring = self.logTxt.GetValue()
    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
            self.progressBox.Bind(wx.EVT_SET_FOCUS, self.highlightText(startPos, endPos))
            startPos = 0
            self.findNextBtn.Enable() 
    
    def findNext(self,e):
    global wordPos
    newstring = self.logTxt.GetValue()
    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
                self.progressBox.Bind(wx.EVT_SET_FOCUS, self.highlightText(startPos, endPos))
                count = 1
    
    
    def highlightText(self, pos, size):
    self.progressBox.SetStyle(pos, size, wx.TextAttr("black", "turquoise"))
    self.progressBox.SetInsertionPoint(pos)
    
Borgme
  • 55
  • 6

1 Answers1

0

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

  • The ability to search the same word, and have the next word highlighted e.g a 'Find Next'

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.

  • Un-highlight the current word when a new word is searched, be it the same word, or a new word

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

  • Start the position at 0 (top of the data) if searching a 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
Borgme
  • 55
  • 6
  • Anyone ending up here might also appreciate to look at the `wx.FindReplaceDialog` as explained [here](https://stackoverflow.com/a/3828378/4041795). – Montmons May 18 '18 at 20:40