Text styling in QTableView with PySide2

后端 未结 1 1999
借酒劲吻你
借酒劲吻你 2021-01-17 04:36

I have a QTableView populated with a proper model. I would like to change the style of the text based on the context of it:

The text, if there is something between p

相关标签:
1条回答
  • 2021-01-17 04:54

    You have to use a delegate that uses QTextDocument:

    import random
    from PySide2 import QtCore, QtGui, QtWidgets
    
    words = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
    Mauris euismod cursus mi sit amet pellentesque. 
    Proin sed lectus sed augue scelerisque congue eget quis leo. 
    Curabitur ultrices nisi nisi, placerat gravida urna sagittis et. 
    Nullam vitae urna tortor. Curabitur a lobortis metus, et laoreet arcu. 
    Quisque a mi in purus molestie porta non sit amet purus. 
    Sed porta non purus et suscipit.'''.split()
    
    class HighlightDelegate(QtWidgets.QStyledItemDelegate):
        def __init__(self, parent=None):
            super(HighlightDelegate, self).__init__(parent)
            self.doc = QtGui.QTextDocument(self)
            self._regex = QtCore.QRegularExpression()
            self._highlight_format = QtGui.QTextCharFormat()
    
        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()
            highlightCursor = QtGui.QTextCursor(self.doc)
            while not highlightCursor.isNull() and not highlightCursor.atEnd():
                highlightCursor = self.doc.find(self.regex, highlightCursor)
                if not highlightCursor.isNull():
                    highlightCursor.mergeCharFormat(self.highlightFormat)
            cursor.endEditBlock()
    
        @property
        def regex(self):
            return self._regex
    
        @regex.setter
        def regex(self, regex):
            if self._regex == regex: return
            self._regex = regex
    
        @property
        def highlightFormat(self):
            return self._highlight_format
    
        @highlightFormat.setter
        def highlightFormat(self, fmt):
            self._highlight_format = fmt
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.table = QtWidgets.QTableView()
    
            self._delegate = HighlightDelegate(self.table)
            self._delegate.regex = QtCore.QRegularExpression(r"\(.*?\)")
            fmt = QtGui.QTextCharFormat()
            fmt.setForeground(QtCore.Qt.green)
            fmt.setFontWeight(QtGui.QFont.Bold)
            self._delegate.highlightFormat = fmt
            self.table.setItemDelegate(self._delegate)
    
            model = QtGui.QStandardItemModel(10, 4)
            for i in range(model.rowCount()):
                for j in range(model.columnCount()):
                    item = QtGui.QStandardItem("{}({}){}".format(*random.sample(words,3)))
                    model.setItem(i, j, item)
            self.table.setModel(model)
            self.setCentralWidget(self.table)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    

    0 讨论(0)
提交回复
热议问题