以前的问题的新功能,有关使用PySide2在QTableView中进行文本样式设置

时间:2019-01-25 03:27:58

标签: python text styling qtableview pyside2

它与previous question有关。 如果现在将括号(包括括号)之间的文本替换为另一文本,那么将颜色保留在替换文本上是否很复杂(即使没有任何限制器或其他限制)?我有一个切换功能,可以更改此设置,并且可以很好地保持替换颜色。

在这里修改了代码示例,使其满足新条件(现在双击可以更改(切换)项目文本:

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)
        self.table.doubleClicked.connect(self.handleDoubleClickTV)

        r = 10
        c = 4
        self.model = QtGui.QStandardItemModel(r, c)
        self.str_items = [["" for i in range(c)] for j in range(r)]
        self.idx_items = [[0 for i in range(c)] for j in range(r)]
        self.setModel()
        self.setCentralWidget(self.table)

    def setModel(self):
        r = self.model.rowCount()
        c = self.model.columnCount()


        for i in range(r):
            for j in range(c):
                random_words = random.sample(words,4)
                str_item1 = "{}({}){}".format(*random_words[:-1]) # words 1, 2, 3
                str_item2 = "{}{}{}".format(*[random_words[0],random_words[3],random_words[2]]) #words 1,4,3
                item = QtGui.QStandardItem(str_item1)
                item.setEditable(False)
                self.str_items[i][j] = [str_item1, str_item2, item]
                self.model.setItem(i, j, item)
        self.table.setModel(self.model)

    def toggleText(self):
        model_index = self.table.selectedIndexes()[0]
        row = model_index.row()
        col = model_index.column()
        index = int(not self.idx_items[row][col])
        # toggle the str
        new_str_item = self.str_items[row][col][index]
        # get item
        item = self.str_items[row][col][2]
        item.setText(new_str_item)
        self.idx_items[row][col] = index

    def handleDoubleClickTV(self):
        self.toggleText()

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

0 个答案:

没有答案