Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

pyqt5 - How can I highlight words dynamically in QTextEdit using Python?

I am trying to create a Text Matcher application using Python. I want to highlight the unmatched words dynamically in the QTextEdit. I am using eventFilter to match the text.

def eventFilter(self, obj, event):
    if obj is self.textEdit_2 and event.type() == QtCore.QEvent.KeyPress:
        if event.key() == QtCore.Qt.Key_Space:
            self.check()
        if event.key() == QtCore.Qt.Key_Backspace:
            self.textEdit_2.insertPlainText("")
            return True
    return super(MainWindow, self).eventFilter(obj, event)

Here is the text matching code:

def check(self):
    var=self.textEdit.toPlainText().split()
    var2=self.textEdit_2.toPlainText().split()
    i=len(var2)-1
    if var[i]!=var2[i]:
        sw=var2.pop()
        self.textEdit_2.clear()
        self.textEdit_2.append(' '.join(var2)+' '+f"<span style='background-color: yellow;'>{sw}</p>")

I need to highlight the words in textedit_2 which do not match in textEdit.

question from:https://stackoverflow.com/questions/65921456/how-can-i-highlight-words-dynamically-in-qtextedit-using-python

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have to install a filterObj to your QTextEdit widget (Doc: QObject::installEventFilter()) inside the __init__() builder of your `MainWindow.

Now, your code will work fine, except for one thing: when you write more words in the second TextEdit, the program will no recognize the error.

Doing some "improvements" to your code (Just to test, if you cando it better, perfect) your __init__() will look like this:

def __init__(self):
    ...# some code to build your app
    self.textEdit_2.installEventFilter(self) ## <<---HERE IS THE CRUCIAL PART
    self.good = True

, your eventFilter() will look like this:

def eventFilter(self, obj, event):
    if obj is self.textEdit_2 and event.type() == QtCore.QEvent.KeyPress:
        if event.key() == QtCore.Qt.Key_Space:
            self.check()
        elif event.key() == QtCore.Qt.Key_Backspace:
            self.textEdit_2.clear()
            self.good = True
            return True
        else:
            if not self.good:
                var2 = self.textEdit_2.toPlainText().split()
                sw = var2.pop()
                self.textEdit_2.clear()
                self.textEdit_2.append(' '.join(var2)+' '+f"<span style='background-color: yellow;'>{sw}</p>")
                self.good = False           
    return super(MainWindow, self).eventFilter(obj, event)

And, finally, your check() will look like this:

def check(self):
    var = self.textEdit.toPlainText().split()
    var2 = self.textEdit_2.toPlainText().split()
    j = len(var)-1
    i = len(var2)-1
    if i-j <= 0:
        if var[i] != var2[i]:
            sw = var2.pop()
            self.textEdit_2.clear()
            self.textEdit_2.append(' '.join(var2)+' '+f"<span style='background-color: yellow;'>{sw}</p>")
            self.good = False
    elif i-j == 1:
        sw = var2.pop()
        self.textEdit_2.clear()
        self.textEdit_2.append(' '.join(var2)+' '+f"<span style='background-color: yellow;'>{sw}</p>")
        self.good = False

The self.good is just a bool variable that I made to let your App know if the current text has errors or not. Here is how it look when I run a simple App I did to test if it works:

enter image description here

Edit

To find all the errors in the second QTextEdit

Now, you commented that you need to find all the errors in textEdit_2. So I did these:

  • Delete the self.good bool variable I made before.
  • Change a bit the eventFilter() function
  • Rewrite your check() function.

The code is here:

def __init__(self):
    ...# some code to build your app
    self.textEdit_2.installEventFilter(self)

def eventFilter(self, obj, event):
    if obj is self.textEdit_2 and event.type() == QtCore.QEvent.KeyPress:
        if event.key() == QtCore.Qt.Key_Space:
            self.check()
        elif event.key() == QtCore.Qt.Key_Backspace:
            self.textEdit_2.clear()
            return True        
    return super(MainWindow, self).eventFilter(obj, event)

def check(self):
    var_1 = self.textEdit.toPlainText().split()
    var_2 = self.textEdit_2.toPlainText().split()
    len_1 = len(var_1)
    len_2 = len(var_2)
    self.textEdit_2.clear()
    text = []
    for it in range(len_2):
        if it < len_1:
            if var_1[it] == var_2[it]:
                text += [var_2[it]]
            else:
                text += ["<span style='background-color: yellow;'>"+var_2[it]+"</span>"]
        else:
            text += ["<span style='background-color: yellow;'>"+var_2[it]+"</span>"]
    text = ' '.join(text)
    self.textEdit_2.append(text)   

And It looks like this:

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...