为了账号安全,请及时绑定邮箱和手机立即绑定

PyQT5 和使用多列筛选表

PyQT5 和使用多列筛选表

摇曳的蔷薇 2022-08-11 17:12:51
我正在尝试制作一个GUI来以表格的形式显示Pandas数据帧,并提供列过滤选项,类似于Microsoft Excel过滤器。到目前为止,我设法采用了类似的SO答案。这是我在 GUI 中的表的图片:PyQt5如上图所示,有两种方法可以过滤列:正则表达式过滤器和单击每列。但是,有一个问题我需要帮助解决:当前应用的筛选器(正则表达式筛选器或列单击)在筛选第二列时消失。我希望第二个过滤器为,即满足列1列2的过滤器。ANDAND
查看完整描述

1 回答

?
慕容3067478

TA贡献1773条经验 获得超3个赞

如果要实现自定义筛选过程,则必须重写 filterAcceptsRow 方法,获取每列的文本并验证它们是否满足条件,如果它们确实返回 True,否则返回 False。若要重新计算筛选器,必须调用无效筛选器方法:


class CustomProxyModel(QtCore.QSortFilterProxyModel):

    def __init__(self, parent=None):

        super().__init__(parent)

        self._filters = dict()


    @property

    def filters(self):

        return self._filters


    def setFilter(self, expresion, column):

        if expresion:

            self.filters[column] = expresion

        elif column in self.filters:

            del self.filters[column]

        self.invalidateFilter()


    def filterAcceptsRow(self, source_row, source_parent):

        for column, expresion in self.filters.items():

            text = self.sourceModel().index(source_row, column, source_parent).data()

            regex = QtCore.QRegExp(

                expresion, QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp

            )

            if regex.indexIn(text) == -1:

                return False

        return True

class myWindow(QtWidgets.QMainWindow):

    # ...


    def load_sites(self):

        # ...


        self.model = PandasModel(df)

        self.proxy = CustomProxyModel(self)

        self.proxy.setSourceModel(self.model)

        self.view.setModel(self.proxy)

        self.view.resizeColumnsToContents()

        print("finished loading sites")


    # ...


    @QtCore.pyqtSlot()

    def on_actionAll_triggered(self):

        filterColumn = self.logicalIndex

        self.proxy.setFilter("", filterColumn)


    @QtCore.pyqtSlot(int)

    def on_signalMapper_mapped(self, i):

        stringAction = self.signalMapper.mapping(i).text()

        filterColumn = self.logicalIndex

        self.proxy.setFilter(stringAction, filterColumn)


    @QtCore.pyqtSlot(str)

    def on_lineEdit_textChanged(self, text):

        self.proxy.setFilter(text, self.proxy.filterKeyColumn())


    @QtCore.pyqtSlot(int)

    def on_comboBox_currentIndexChanged(self, index):

        self.proxy.setFilterKeyColumn(index)

加:如果要更改 QHeaderView 的字体,则必须在 headerData 中返回该字体,如下所示:


class PandasModel(QtCore.QAbstractTableModel):

    def __init__(self, df=pd.DataFrame(), parent=None):

        QtCore.QAbstractTableModel.__init__(self, parent=parent)

        self._df = df.copy()

        self.bolds = dict()


    def toDataFrame(self):

        return self._df.copy()


    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):

        if orientation == QtCore.Qt.Horizontal:

            if role == QtCore.Qt.DisplayRole:

                try:

                    return self._df.columns.tolist()[section]

                except (IndexError,):

                    return QtCore.QVariant()

            elif role == QtCore.Qt.FontRole:

                return self.bolds.get(section, QtCore.QVariant())

        elif orientation == QtCore.Qt.Vertical:

            if role == QtCore.Qt.DisplayRole:

                try:

                    # return self.df.index.tolist()

                    return self._df.index.tolist()[section]

                except (IndexError,):

                    return QtCore.QVariant()

        return QtCore.QVariant()


    def setFont(self, section, font):

        self.bolds[section] = font

        self.headerDataChanged.emit(QtCore.Qt.Horizontal, 0, self.columnCount())

    # ...

class myWindow(QtWidgets.QMainWindow):

    # ...

   @QtCore.pyqtSlot()

    def on_actionAll_triggered(self):

        filterColumn = self.logicalIndex

        self.proxy.setFilter("", filterColumn)

        font = QtGui.QFont()

        self.model.setFont(filterColumn, font)


    @QtCore.pyqtSlot(int)

    def on_signalMapper_mapped(self, i):

        stringAction = self.signalMapper.mapping(i).text()

        filterColumn = self.logicalIndex

        self.proxy.setFilter(stringAction, filterColumn)

        font = QtGui.QFont()

        font.setBold(True)

        self.model.setFont(filterColumn, font)


查看完整回答
反对 回复 2022-08-11
  • 1 回答
  • 0 关注
  • 394 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信