在 QTreeView 列中查找第一次出现的文本

Find first occurrence of a text inside a QTreeView-column

在我的主要 window 中,我有一个 table 的 class QTreeView。第二列包含邮件主题。通过点击一个按钮,我想搜索一个特定的字符,比方说 "Y"。现在我希望 table 跳转到第一个找到的以字母 "Y".

开头的主题

请参阅以下示例。

当您选择第二列 ("subject") 中的任何单元格并开始键入 "y" 时,这将起作用 -> table 突出显示第一个匹配项。 -> 请参阅带下划线的项目 "Your Phone Bill"。当它看不见时,它甚至会滚动到那个单元格。

我正是想要这个 - 但在按钮上实现,参见 "Search Subj 'Y'",信号 "on_pbSearch_Y_clicked()"。

完整功能代码(到目前为止):

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

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

    def __init__(self):
        super().__init__()      
        self.left = 10
        self.top = 10
        self.width = 640
        self.height = 240
        self.initUI()

        self.dataView.setSelectionMode(QAbstractItemView.ExtendedSelection)  #  <- enable selection of rows in tree
        self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers)      #  <- disable editing items in tree

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

        self.pbSearch_Y = QPushButton(self)
        self.pbSearch_Y.setText("Search Subj 'Y'")
        self.pbSearch_Y.move(500,0)        

        self.pbSearch_Y.show()

        # connect handlers        
        self.pbSearch_Y.clicked.connect(self.on_pbSearch_Y_clicked)

    def on_pbSearch_Y_clicked(self):
        pass

    def initUI(self):        
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.dataGroupBox = QGroupBox("Inbox")
        self.dataView = QTreeView()
        self.dataView.setRootIsDecorated(False)
        self.dataView.setAlternatingRowColors(True)        

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

        model = self.createMailModel(self)
        self.dataView.setModel(model)
        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)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.dataGroupBox)
        self.setLayout(mainLayout)

        self.show()

    def createMailModel(self,parent):
        model = QStandardItemModel(0, self.MAIL_RANGE, parent)
        model.setHeaderData(self.ID, Qt.Horizontal, "ID")
        model.setHeaderData(self.FROM, Qt.Horizontal, "From")
        model.setHeaderData(self.SUBJECT, Qt.Horizontal, "Subject")
        model.setHeaderData(self.DATE, Qt.Horizontal, "Date")
        return model

    def addMail(self, model, mailID, mailFrom, subject, date):
        model.insertRow(0)
        model.setData(model.index(0, self.ID), mailID)
        model.setData(model.index(0, self.FROM), mailFrom)
        model.setData(model.index(0, self.SUBJECT), subject)
        model.setData(model.index(0, self.DATE), date)        

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

我怎样才能做到这一点?

老实说,我不将 GUI 与 python 一起使用,但您可以通过使用 PyQT

将我的任意函数替换为所需的函数来实现这一点
mostWantedChar = 'Y'
foundElements = []
for element in dataView.listElements():
    if element[0] == mostWantedChar:
        foundElements.Append(element + '@' + element.Line()) #In case you would need to get the line and the line's content for further purposes (just make a split('@') )
        element.Line().Higlight()
    waitClickFromPushButton()
return foundElements

您必须执行以下操作:

#!/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:
            # find index
            start = self.dataView.model().index(0, 2)
            ixs = self.dataView.model().match(
                start,
                QtCore.Qt.DisplayRole,
                text,
                hits=1,
                flags=QtCore.Qt.MatchStartsWith,
            )
            if ixs:
                ix = ixs[0]

                # scroll to index
                self.dataView.scrollTo(ix)

                # select row
                ix_from = ix.sibling(ix.row(), 0)
                ix_to = ix.sibling(
                    ix.row(), self.dataView.model().columnCount() - 1
                )
                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_())