在 PYQT5 中突出显示 QTableWidget 单元格中的特定单词

Highlight specific words in a QTableWidget cell in PYQT5

我需要一些关于如何在 QTableWidget 单元格中突出显示特定单词的帮助。例如在这张图片中。假设我想用绿色突出显示 "James" 这个词。有些单词 “James” 是完整单词,而那些不是完整单词的单词仍然需要突出显示

现在请注意,我已经对此进行了搜索,并且找到了类似的解决方案并对其进行了研究(这真的很酷!)。 。但是似乎有些部分与我的目标不同并且相当复杂,而我的非常非常简单。就像当 table 有它的数据时它会突出显示一个选定的词,我相信这可以很容易地用更短的代码或更简单的方法来实现一个词的着色。我需要一些帮助,我觉得这真的很棒,并期待着完成它。

下面就拿这个示例代码和一个简单的PYQT5 QTableWidget来做个测试吧

import sys 
from PyQt5.QtWidgets import * 
                    
   
#Main Window 
class App(QWidget): 
    def __init__(self): 
        super().__init__() 
        self.title = 'PyQt5 - QTableWidget'
        self.left = 0
        self.top = 0
        self.width = 300
        self.height = 200
   
        self.setWindowTitle(self.title) 
        self.setGeometry(self.left, self.top, self.width, self.height) 
   
        self.createTable() 
   
        self.layout = QVBoxLayout() 
        self.layout.addWidget(self.tableWidget) 
        self.setLayout(self.layout) 
   
        #Show window 
        self.show() 
   
    #Create table 
    def createTable(self): 
        self.tableWidget = QTableWidget() 
  
        #Row count 
        self.tableWidget.setRowCount(4)  
  
        #Column count 
        self.tableWidget.setColumnCount(2)   
  
        self.tableWidget.setItem(0,0, QTableWidgetItem("Name")) 
        self.tableWidget.setItem(0,1, QTableWidgetItem("City")) 
        self.tableWidget.setItem(1,0, QTableWidgetItem("Lebron James")) 
        self.tableWidget.setItem(1,1, QTableWidgetItem("King James")) 
        self.tableWidget.setItem(2,0, QTableWidgetItem("KingJames")) 
        self.tableWidget.setItem(2,1, QTableWidgetItem("Champions")) 
        self.tableWidget.setItem(3,0, QTableWidgetItem("World")) 
        self.tableWidget.setItem(3,1, QTableWidgetItem("2020")) 
   
        #Table will fit the screen horizontally 
        self.tableWidget.horizontalHeader().setStretchLastSection(True) 
        self.tableWidget.horizontalHeader().setSectionResizeMode( 
            QHeaderView.Stretch) 
   
if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    ex = App() 
    sys.exit(app.exec_()) 

研究类似答案中的代码非常具有挑战性,但我设法弄明白了,这是代码。我仍然好奇的唯一一件事是是否有更简单的方法来做到这一点,因为我一直在研究代码并思考真正发生的事情以及所有这些必要的事情。但无论如何,如果没有,我将继续实施此 的解决方案。谢谢!

import sys, re
from PyQt5.QtWidgets import * 
from PyQt5 import QtCore, QtGui, QtWidgets
   
#Main Window 
class App(QWidget): 
    def __init__(self): 
        super().__init__() 
        self.title = 'PyQt5 - QTableWidget'
        self.left = 0
        self.top = 0
        self.width = 300
        self.height = 200
   
        self.setWindowTitle(self.title) 
        self.setGeometry(self.left, self.top, self.width, self.height) 
   
        self.createTable() 
   
        self.layout = QVBoxLayout() 
        self.layout.addWidget(self.tableWidget) 
        self.setLayout(self.layout) 
   
        #Show window 
        self.show() 
   
    #Create table 
    def createTable(self): 
        self.tableWidget = QTableWidget() 
        self._delegate = HighlightDelegate(self.tableWidget)
        self.tableWidget.setItemDelegate(self._delegate)
  
        #Row count 
        self.tableWidget.setRowCount(4)  
  
        #Column count 
        self.tableWidget.setColumnCount(2)   
  
        self.tableWidget.setItem(0,0, QTableWidgetItem("Name")) 
        self.tableWidget.setItem(0,1, QTableWidgetItem("City")) 
        self.tableWidget.setItem(1,0, QTableWidgetItem("Lebron James")) 
        self.tableWidget.setItem(1,1, QTableWidgetItem("King James")) 
        self.tableWidget.setItem(2,0, QTableWidgetItem("KingJames")) 
        self.tableWidget.setItem(2,1, QTableWidgetItem("Champions")) 
        self.tableWidget.setItem(3,0, QTableWidgetItem("World")) 
        self.tableWidget.setItem(3,1, QTableWidgetItem("2020")) 
   
        #Table will fit the screen horizontally 
        self.tableWidget.horizontalHeader().setStretchLastSection(True) 
        self.tableWidget.horizontalHeader().setSectionResizeMode( 
            QHeaderView.Stretch) 

        #Started coloring
        self.on_textChanged()



    def on_textChanged(self, text="James"):
        self._delegate.setFilters(list(set(text.split())))
        self.tableWidget.viewport().update()












class HighlightDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HighlightDelegate, self).__init__(parent)
        self.doc = QtGui.QTextDocument(self)
        self._filters = []

    def paint(self, painter, option, index):
        painter.save()
        options = QtWidgets.QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        self.doc.setPlainText(options.text)
        self.apply_highlight(options.text)

        
        options.text = ""
        style = QtWidgets.QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter)

        ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
        if option.state & QtWidgets.QStyle.State_Selected:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
                QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
        else:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
                QtGui.QPalette.Active, QtGui.QPalette.Text))

        textRect = style.subElementRect(
            QtWidgets.QStyle.SE_ItemViewItemText, options)

        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)

        the_constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - the_constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()
        

    def apply_highlight(self,text):
        cursor = QtGui.QTextCursor(self.doc)
        cursor.beginEditBlock()
        fmt = QtGui.QTextCharFormat()

        highlight_word = ''.join(self.filters())
        print(text)
        sentence_status = re.search(r'\b'+ highlight_word + r'\b',text,re.IGNORECASE)

        if sentence_status != None:
            fmt.setForeground(QtCore.Qt.darkGreen)
        else:
            fmt.setForeground(QtCore.Qt.red)


        for f in self.filters():
            highlightCursor = QtGui.QTextCursor(self.doc)
            while not highlightCursor.isNull() and not highlightCursor.atEnd():
                highlightCursor = self.doc.find(f, highlightCursor)
                if not highlightCursor.isNull():
                    highlightCursor.mergeCharFormat(fmt)
        cursor.endEditBlock()

    @QtCore.pyqtSlot(list)
    def setFilters(self, filters):
        if self._filters == filters: return
        self._filters = filters

    def filters(self):
        return self._filters



















if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    ex = App() 
    sys.exit(app.exec_())