如何筛选出个别项目,而不是仅仅在行和列的基础上?

2024-04-25 22:20:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图根据字符串匹配筛选出表中的项。你知道吗

我有一个QTableView显示代理模型以允许过滤,但是如果(0,0)和(1,1)中的项目与我的字符串匹配,但项目(1,0)不匹配,它仍将显示。你知道吗

例如:

from PySide.QtGui import *
from PySide.QtCore import *


class CustomProxyFilter(QSortFilterProxyModel):

    def __init__(self):
        super(CustomProxyFilter, self).__init__()

    def filterAcceptsColumn(self, source_column, parent):
        """Re-implementing built-in to hide columns with non matches."""
        model = self.sourceModel()
        matched_string = self.filterRegExp().pattern().lower()
        for row in range(model.rowCount()):
            item = model.item(row, source_column)
            if item and matched_string in model.item(row, source_column).text().lower():
                return True
        return False


class CustomTableView(QTableView):
    """Table view."""
    def __init__(self, line_edit):
        super(CustomTableView, self).__init__()

        custom_model = StandardTableModel()

        items = ["apple", "banana", "applebanana"]
        for i, item in enumerate(items):
            for v, second_item in enumerate(items):
                custom_model.setItem(i, v, QStandardItem(item))
        self.proxy_model = CustomProxyFilter()
        self.proxy_model.setSourceModel(custom_model)
        self.setModel(self.proxy_model)


        line_edit.textChanged.connect(self.proxy_model.setFilterRegExp)


class Window(QWidget):

    def __init__(self):
        super(Window, self).__init__()
        self.setLayout(QVBoxLayout())
        self.line_edit = QLineEdit()
        self.layout().addWidget(self.line_edit)
        self.layout().addWidget(CustomTableView(self.line_edit))

我希望如果我的桌子看起来像

a|b|c
-----
c|a|b

按“a”筛选后的结果表将是

a|a

我现在的解决方案显示。你知道吗

a|b
---
c|a

更新其他案例

a|a|c
-----
a|x|b
-----
c|b|a

变成

a|a|a
-----
a

这个案子

a|a|y|c
-------
a|a|w|a
-------
c|a|w|w

变成

a|a|a|a
-----
a|a|

基本上,每一个项目都会向左上角移动。当他们是不同的名字时,他们会这样按字母顺序排列

1|2|3|4
-------
5|6|7|8

Tags: 项目inselfsourcemodelinitdefline
1条回答
网友
1楼 · 发布于 2024-04-25 22:20:59

为了实现您所需要的功能,我以以下方式实现了几个连接的代理:

model >Table2ListProxyModel >QSortFilterProxyModel >List2TableProxyModel

其思想是将其转换为列表的结构,因为过滤一行相当于过滤一个项目,相同的代理对其进行排序,然后我们将列表转换为一个表。你知道吗

import math
from PySide import QtCore, QtGui


class Table2ListProxyModel(QtGui.QSortFilterProxyModel):
    def columnCount(self, parent=QtCore.QModelIndex()):
        return 1

    def rowCount(self, parent=QtCore.QModelIndex()):
        if parent.isValid():
            return 0
        return self.sourceModel().rowCount() * self.sourceModel().columnCount()

    def mapFromSource(self, sourceIndex):
        if (
            sourceIndex.isValid()
            and sourceIndex.column() == 0
            and sourceIndex.row() < self.rowCount()
        ):
            r = sourceIndex.row()
            c = sourceIndex.column()
            row = c * sourceIndex.model().columnCount() + r
            return self.index(row, 0)
        return QtCore.QModelIndex()

    def mapToSource(self, proxyIndex):
        r = proxyIndex.row() / self.sourceModel().columnCount()
        c = proxyIndex.row() % self.sourceModel().columnCount()
        return self.sourceModel().index(r, c)

    def index(self, row, column, parent=QtCore.QModelIndex()):
        return self.createIndex(row, column)


class List2TableProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self, columns=1, parent=None):
        super(List2TableProxyModel, self).__init__(parent)
        self._columns = columns

    def columnCount(self, parent=QtCore.QModelIndex()):
        r = self.sourceModel().rowCount()
        if r < self._columns:
            return r
        return self._columns

    def rowCount(self, parent=QtCore.QModelIndex()):
        if parent.isValid():
            return 0
        row = math.ceil(self.sourceModel().rowCount()*1.0 / self._columns)
        return row

    def index(self, row, column, parent=QtCore.QModelIndex()):
        return self.createIndex(row, column)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        r = index.row()
        c = index.column()
        row = r * self.columnCount() + c
        if row < self.sourceModel().rowCount():
            return super(List2TableProxyModel, self).data(index, role)

    def mapFromSource(self, sourceIndex):
        r = math.ceil(sourceIndex.row()*1.0 / self.columnCount())
        c = sourceIndex.row() % self.columnCount()
        return self.index(r, c)

    def mapToSource(self, proxyIndex):
        if proxyIndex.isValid():
            r = proxyIndex.row()
            c = proxyIndex.column()
            row = r * self.columnCount() + c
            return self.sourceModel().index(row, 0)
        return QtCore.QModelIndex()

    def setSourceModel(self, model):
        model.rowsRemoved.connect(self.reset_model)
        model.rowsInserted.connect(self.reset_model)
        model.dataChanged.connect(self.reset_model)
        model.rowsMoved.connect(self.reset_model)
        model.layoutChanged.connect(self.reset_model)
        model.modelReset.connect(self.reset_model)
        super(List2TableProxyModel, self).setSourceModel(model)

    @QtCore.Slot()
    def reset_model(self):
        QtCore.QTimer.singleShot(0, self.invalidate)

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            return str(section)
        return super(List2TableProxyModel, self).headerData(
            section, orientation, role
        )


class CustomTableView(QtGui.QTableView):
    def __init__(self, parent=None):
        super(CustomTableView, self).__init__(parent)
        custom_model = QtGui.QStandardItemModel()
        datas = (("ad", "cd", "ef"), ("ab", "ce", "eg"), ("aa", "cb", "eh"))
        for i, data in enumerate(datas):
            for v, text in enumerate(data):
                custom_model.setItem(i, v, QtGui.QStandardItem(text))
        self.proxy_list = Table2ListProxyModel(self)
        self.proxy_list.setSourceModel(custom_model)
        self.proxy_sort_filter = QtGui.QSortFilterProxyModel(self)
        self.proxy_sort_filter.setSourceModel(self.proxy_list)
        self.proxy_table = List2TableProxyModel(
            columns=custom_model.columnCount(), parent=self
        )
        self.proxy_table.setSourceModel(self.proxy_sort_filter)

        self.setModel(self.proxy_table)

    @QtCore.Slot(str)
    def setFilter(self, text):
        self.proxy_sort_filter.setFilterWildcard(
            "*{}*".format(text) if text else ""
        )
        self.proxy_sort_filter.sort(0 if text else -1, QtCore.Qt.AscendingOrder)


class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.line_edit = QtGui.QLineEdit()
        self.tableview = CustomTableView()

        lay = QtGui.QVBoxLayout(self)
        lay.addWidget(self.line_edit)
        lay.addWidget(self.tableview)
        self.line_edit.textChanged.connect(self.tableview.setFilter)


if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

enter image description here

enter image description here

enter image description here

相关问题 更多 >