首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何遍历QTreeView并给所有匹配的单元格上色?

如何遍历QTreeView并给所有匹配的单元格上色?
EN

Stack Overflow用户
提问于 2019-06-10 02:55:47
回答 1查看 189关注 0票数 1

当按下搜索按钮时,我想搜索QTreeView的所有项目(也就是单元格),并通过CSS样式对所有与搜索到的文本单元格匹配的单元格进行着色。

这个是可能的吗?

当前代码(完整工作示例):

代码语言:javascript
复制
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class App(QtWidgets.QWidget):
    MAIL_RANGE = 4
    ID, FROM, SUBJECT, DATE = range(MAIL_RANGE)

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(10, 10, 640, 240)

        self.dataGroupBox = QtWidgets.QGroupBox("Inbox")
        self.dataView = QtWidgets.QTreeView(
            rootIsDecorated=False,
            alternatingRowColors=True,
            selectionMode=QtWidgets.QAbstractItemView.ExtendedSelection,
            editTriggers=QtWidgets.QAbstractItemView.NoEditTriggers,
            selectionBehavior=QtWidgets.QAbstractItemView.SelectRows,
        )

        dataLayout = QtWidgets.QHBoxLayout()
        dataLayout.addWidget(self.dataView)
        self.dataGroupBox.setLayout(dataLayout)

        model = App.createMailModel(self)
        self.dataView.setModel(model)

        for i in range(0, 2):
            self.dataView.resizeColumnToContents(i)

        self.addMail(model, 1, 'service@github.com', 'Your Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 2, 'support@github.com', 'Github Projects','02/02/2017 03:05 PM')
        self.addMail(model, 3, 'service@phone.com', 'Your Phone Bill','01/01/2017 04:05 PM')
        self.addMail(model, 4, 'service@abc.com', 'aaaYour Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 5, 'support@def.com', 'bbbGithub Projects','02/02/2017 03:05 PM')
        self.addMail(model, 6, 'service@xyz.com', 'cccYour Phone Bill','01/01/2017 04:05 PM')

        self.dataView.setColumnHidden(0, True)

        self.leSearch = QtWidgets.QLineEdit()
        self.pbSearch = QtWidgets.QPushButton(
            "Search", clicked=self.on_pbSearch_clicked
        )

        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(self.leSearch)
        hlay.addWidget(self.pbSearch)

        mainLayout = QtWidgets.QVBoxLayout(self)
        mainLayout.addLayout(hlay)
        mainLayout.addWidget(self.dataGroupBox)

    @staticmethod
    def createMailModel(parent):
        model = QtGui.QStandardItemModel(0, App.MAIL_RANGE, parent)
        for c, text in zip(
            (App.ID, App.FROM, App.SUBJECT, App.DATE),
            ("ID", "From", "Subject", "Date"),
        ):
            model.setHeaderData(c, QtCore.Qt.Horizontal, text)
        return model

    def addMail(self, model, mailID, mailFrom, subject, date):
        model.insertRow(0)
        for c, text in zip(
            (App.ID, App.FROM, App.SUBJECT, App.DATE),
            (mailID, mailFrom, subject, date),
        ):
            model.setData(model.index(0, c), text)

    @QtCore.pyqtSlot()
    def on_pbSearch_clicked(self):
        text = self.leSearch.text()
        self.leSearch.clear()
        if text:
            start = self.dataView.model().index(0, 2)
            # find index
            ixs = self.dataView.model().match(
                start,
                QtCore.Qt.DisplayRole,
                text,
                flags=QtCore.Qt.MatchStartsWith,
            )
            if ixs:
                ix = ixs[0]
                # scroll to index
                self.dataView.scrollTo(ix)
                ix_from = ix.sibling(ix.row(), 0)
                ix_to = ix.sibling(
                    ix.row(), self.dataView.model().columnCount() - 1
                )
                # select row
                self.dataView.selectionModel().select(
                    QtCore.QItemSelection(ix_from, ix_to),
                    QtCore.QItemSelectionModel.SelectCurrent,
                )
        else:
            self.dataView.clearSelection()


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

请参阅method on_pbSearch_clicked ->,此处所有匹配的行都被标记为选中。相反,我想通过CSS样式给单元格上色。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-10 05:56:07

您可以使用委托来设置背景和文本颜色,还可以使用角色来指示应该绘制哪个单元格。

代码语言:javascript
复制
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtGui, QtWidgets


MatchRole = QtCore.Qt.UserRole + 1000


class HighlightDelegate(QtWidgets.QStyledItemDelegate):
    @property
    def background(self):
        if not hasattr(self, "_background"):
            self._background = QtGui.QBrush()
        return self._background

    @background.setter
    def background(self, brush):
        self._background = QtGui.QBrush(brush)

    @property
    def foreground(self):
        if not hasattr(self, "_foreground"):
            self._foreground = QtGui.QBrush()
        return self._foreground

    @foreground.setter
    def foreground(self, brush):
        self._foreground = QtGui.QBrush(brush)

    def initStyleOption(self, option, index):
        super(HighlightDelegate, self).initStyleOption(option, index)
        if index.data(MatchRole):
            if self.background != QtGui.QBrush():
                option.backgroundBrush = self.background
            if self.foreground != QtGui.QBrush():
                option.palette.setBrush(QtGui.QPalette.Text, self.foreground)


class App(QtWidgets.QWidget):
    MAIL_RANGE = 4
    ID, FROM, SUBJECT, DATE = range(MAIL_RANGE)

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(10, 10, 640, 240)

        self.dataGroupBox = QtWidgets.QGroupBox("Inbox")
        self.dataView = QtWidgets.QTreeView(
            rootIsDecorated=False,
            alternatingRowColors=True,
            selectionMode=QtWidgets.QAbstractItemView.ExtendedSelection,
            editTriggers=QtWidgets.QAbstractItemView.NoEditTriggers,
            selectionBehavior=QtWidgets.QAbstractItemView.SelectRows,
        )

        delegate = HighlightDelegate(self.dataView)
        self.dataView.setItemDelegate(delegate)
        delegate.background = QtGui.QColor("gray")
        delegate.foreground = QtGui.QColor("salmon")
        self.dataView.viewport().update()

        dataLayout = QtWidgets.QHBoxLayout()
        dataLayout.addWidget(self.dataView)
        self.dataGroupBox.setLayout(dataLayout)

        model = App.createMailModel(self)
        self.dataView.setModel(model)

        for i in range(0, 2):
            self.dataView.resizeColumnToContents(i)

        self.addMail(model, 1, 'service@github.com', 'Your Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 2, 'support@github.com', 'Github Projects','02/02/2017 03:05 PM')
        self.addMail(model, 3, 'service@phone.com', 'Your Phone Bill','01/01/2017 04:05 PM')
        self.addMail(model, 4, 'service@abc.com', 'aaaYour Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 5, 'support@def.com', 'bbbGithub Projects','02/02/2017 03:05 PM')
        self.addMail(model, 6, 'service@xyz.com', 'cccYour Phone Bill','01/01/2017 04:05 PM')

        self.dataView.setColumnHidden(0, True)

        for i in range(self.dataView.model().columnCount()):
            self.dataView.header().setSectionResizeMode(i, QtWidgets.QHeaderView.Stretch)

        self.leSearch = QtWidgets.QLineEdit()
        self.pbSearch = QtWidgets.QPushButton(
            "Search", clicked=self.on_pbSearch_clicked
        )

        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(self.leSearch)
        hlay.addWidget(self.pbSearch)

        mainLayout = QtWidgets.QVBoxLayout(self)
        mainLayout.addLayout(hlay)
        mainLayout.addWidget(self.dataGroupBox)

    @staticmethod
    def createMailModel(parent):
        model = QtGui.QStandardItemModel(0, App.MAIL_RANGE, parent)
        for c, text in zip(
            (App.ID, App.FROM, App.SUBJECT, App.DATE),
            ("ID", "From", "Subject", "Date"),
        ):
            model.setHeaderData(c, QtCore.Qt.Horizontal, text)
        return model

    def addMail(self, model, mailID, mailFrom, subject, date):
        model.insertRow(0)
        for c, text in zip(
            (App.ID, App.FROM, App.SUBJECT, App.DATE),
            (mailID, mailFrom, subject, date),
        ):
            model.setData(model.index(0, c), text)

    @QtCore.pyqtSlot()
    def on_pbSearch_clicked(self):
        text = self.leSearch.text()
        # self.leSearch.clear()
        model = self.dataView.model()
        # clear
        for column in range(model.columnCount()):
            for row in range(model.rowCount()):
                ix = model.index(row, column)
                model.setData(ix, False, MatchRole)

        if text:
            for column in range(model.columnCount()):
                start = self.dataView.model().index(0, column)
                ixs = self.dataView.model().match(
                    start,
                    QtCore.Qt.DisplayRole,
                    text,
                    hits=-1,
                    flags=QtCore.Qt.MatchContains,
                )
                for ix in ixs:
                    model.setData(ix, True, MatchRole)


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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56517505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档