如何从搜索列表中突出显示 QTableWidget 中的单词 [英] How to highlight a words in QTableWidget from a Searchlist

查看:51
本文介绍了如何从搜索列表中突出显示 QTableWidget 中的单词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过单词列表搜索 QTableWidget-Table,如果找到它们,我希望它们突出显示.

我试图修改

I want to search a QTableWidget-Table by a list of words, if they've been found i want them to bee highlighted.

I tried to modify the code from here so the table is beeing searched by a list of words, not just one. Unfortunatly my results keep getting overwritten. I always only get the result for the last word in the list.

Does anyone know how to modify the code so it will show the result of the whole list of words ?

Here is the code:

from PyQt5 import QtCore, QtGui, QtWidgets
import random
import html

words_1 = ["Hello dseerfd", "world sdfsdf sdfgsdf sdfsdf", "Stack dasdf", "Overflow", "Hello world", """<font color="red">Hello world</font>"""]

class HTMLDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HTMLDelegate, self).__init__(parent)
        self.doc = QtGui.QTextDocument(self)

    def paint(self, painter, option, index):
        substring = index.data(QtCore.Qt.UserRole)
        painter.save()
        options = QtWidgets.QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        res = ""
        color = QtGui.QColor("red")
        if substring:
            substrings = options.text.split(substring)
            res = """<font color="{}">{}</font>""".format(color.name(QtGui.QColor.HexRgb), substring).join(list(map(html.escape, substrings)))
        else:
            res = html.escape(options.text)
        self.doc.setHtml(res)

        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()


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        hlay = QtWidgets.QHBoxLayout()
        lay = QtWidgets.QVBoxLayout(self)
        self.table = QtWidgets.QTableWidget(5, 5)
        lay.addLayout(hlay)
        lay.addWidget(self.table)



        self.table.setItemDelegate(HTMLDelegate(self.table))

        for i in range(self.table.rowCount()):
            for j in range(self.table.columnCount()):
                it = QtWidgets.QTableWidgetItem(random.choice(words_1))
                self.table.setItem(i, j, it)


        text_list = ['ello', 'ack']
        # clear
        allitems = self.table.findItems("", QtCore.Qt.MatchContains)

        selected_items =[]
        for words in text_list:
            for item in allitems:
                selected_items = self.table.findItems(words, QtCore.Qt.MatchContains)
                selected_items.append(self.table.findItems(words, QtCore.Qt.MatchContains)) ## i tried to make a list which is beeing appened but using this list it returns only the same as the input

                item.setData(QtCore.Qt.UserRole, words if item in selected_items else None)




if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

解决方案

In the previous case I wanted to filter the cases so as not to have to paint unnecessarily but in this case because it was more complex I decided to implement the highlight logic using QTextCharFormat and not HTML as I show below:

from PyQt5 import QtCore, QtGui, QtWidgets
import random

words = ["Hello dseerfd", "world sdfsdf sdfgsdf sdfsdf", "Stack dasdf", "Overflow", "Hello world", """<font color="red">Hello world</font>"""]

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 = ""
        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):
        cursor = QtGui.QTextCursor(self.doc)
        cursor.beginEditBlock()
        fmt = QtGui.QTextCharFormat()
        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

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.table = QtWidgets.QTableWidget(30, 6)
        self._delegate = HighlightDelegate(self.table)
        self.table.setItemDelegate(self._delegate)
        for i in range(self.table.rowCount()):
            for j in range(self.table.columnCount()):
                it = QtWidgets.QTableWidgetItem(random.choice(words))
                self.table.setItem(i, j, it)
        self.table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)

        le = QtWidgets.QLineEdit()
        le.textChanged.connect(self.on_textChanged)
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(le)
        lay.addWidget(self.table)

        le.setText("ello ack")

    @QtCore.pyqtSlot(str)
    def on_textChanged(self, text):
        self._delegate.setFilters(list(set(text.split())))
        self.table.viewport().update()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.showMaximized()
    sys.exit(app.exec_())

这篇关于如何从搜索列表中突出显示 QTableWidget 中的单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆