Python 返回QtCore.QVariant() 如果列>自检列: index=index.sibling(index.row(),col-1) 返回super().数据(索引、角色) def setData(自身、索引、值、角色): 如果可自检_列!=-1: 行,

Python 返回QtCore.QVariant() 如果列>自检列: index=index.sibling(index.row(),col-1) 返回super().数据(索引、角色) def setData(自身、索引、值、角色): 如果可自检_列!=-1: 行,,python,pyqt,pyqt5,qsortfilterproxymodel,Python,Pyqt,Pyqt5,Qsortfilterproxymodel,返回QtCore.QVariant() 如果列>自检列: index=index.sibling(index.row(),col-1) 返回super().数据(索引、角色) def setData(自身、索引、值、角色): 如果可自检_列!=-1: 行,列=index.row(),index.column() 如果col==self.checkable_列: 如果角色==QtCore.Qt.CheckStateRole: 如果行中有可自检的_值: 自我检查_值。放弃(行) 其他: self.c

返回QtCore.QVariant() 如果列>自检列: index=index.sibling(index.row(),col-1) 返回super().数据(索引、角色) def setData(自身、索引、值、角色): 如果可自检_列!=-1: 行,列=index.row(),index.column() 如果col==self.checkable_列: 如果角色==QtCore.Qt.CheckStateRole: 如果行中有可自检的_值: 自我检查_值。放弃(行) 其他: self.checkable_values.add(行) self.dataChanged.emit(索引,索引,(角色,)) 返回真值 返回错误 如果列>自检列: index=index.sibling(index.row(),col-1) return super().setData(索引、值、角色) def headerData(self、section、orientation、role=QtCore.Qt.DisplayRole): 如果可自检_列!=-1: 如果节==self.checkable_列且方向==QtCore.Qt.Horizontal: 返回QtCore.QVariant() 如果节>可自检_列和方向==QtCore.Qt.Horizontal: 截面-=1 return super().headerData(节、方向、角色) def标志(自、索引): 如果可自检_列!=-1: col=index.column() 如果col==self.checkable_列: 返回QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled 如果列>自检列: index=index.sibling(index.row(),col-1) 返回super().标志(索引) 类CustomProxyModel(QtCore.QSortFilterProxyModel): def uuu init uuu(self,parent=None): super()。\uuuu init\uuuu(父级) self.\u filters=dict() @财产 def过滤器(自): 返回自我过滤器 def setFilter(自身、表达式、列): 如果是扩展: self.filters[column]=expresion self.filters中的elif列: del self.filters[列] self.invalidateFilter() def filterAcceptsRow(自身、源行、源父行): 对于列,在self.filters.items()中进行表达式: text=self.sourceModel().index(源\行、列、源\父级).data() regex=QtCore.QRegExp( expresion,QtCore.Qt.case不敏感,QtCore.QRegExp.RegExp ) 如果正则表达式indexIn(文本)=-1: 返回错误 返回真值 类myWindow(QtWidgets.QMainWindow): def uuu init uuu(self,parent=None): 超级(myWindow,self)。\uuuuu init\uuuuuu(父级) self.centralwidget=qtwidts.QWidget() self.lineEdit=qtwidts.QLineEdit() self.view=qtwidts.QTableView() self.comboBox=qtwidts.QComboBox() self.label=qtwidts.QLabel() self.gridLayout=qtwidts.QGridLayout(self.centralwidget) self.gridLayout.addWidget(self.lineEdit,0,1,1) self.gridLayout.addWidget(self.view,1,0,1,3) self.gridLayout.addWidget(self.comboBox,0,2,1,1) self.gridLayout.addWidget(self.label,0,0,1,1) self.setCentralWidget(self.centralwidget) self.label.setText(“正则表达式过滤器”) self.load_站点() self.comboBox.addItems([“{0}”.format(col)表示self.model.\u df.columns中的col]) self.lineEdit.textChanged.connect(self.on\u lineEdit\u textChanged) self.horizontalHeader=self.view.horizontalHeader() self.horizontalHeader.sectionClicked.connect( 单击self.on\u视图\u水平标题\u部分 ) def加载_站点(自身): df=pd.DataFrame( { “现场代码”:[“01”、“02”、“03”、“04”], “状态”:[“打开”、“打开”、“打开”、“关闭”], “位置”:[“东”、“北”、“南”、“东”], “数据质量”:[“差”、“中等”、“高”、“高”], } ) self.model=CheckablePandasModel(df) self.model.checkable_列=0 self.proxy=CustomProxyModel(self) self.proxy.setSourceModel(self.model) self.view.setModel(self.proxy) self.view.resizeColumnsToContents()的大小 @QtCore.pyqtSlot(int) 单击“视图”“水平标题”“部分”上的def(自,逻辑索引): 如果logicalIndex==self.model.checkable_列: 返回 self.menuValues=qtwidts.QMenu(self) self.comboBox.blockSignals(真) self.comboBox.setCurrentIndex( logicalIndex-1 如果logicalIndex>self.model.checkable\u列 else逻辑索引 ) self.comboBox.blockSignals(真) 值SIQUE=set( self.proxy.index(i,logicalIndex.data)() 对于范围内的i(self.proxy.rowCount()) ) actionAll=qtwidts.QAction(“全部”,self) self.menuValues.addAction(actionAll) self.menuValues.addSeparator() 对于i,枚举中的名称(valuesUnique): action=qtwidts.QAction(名称,self) 行动.设置数据(i) self.menuValues.addAction(操作) headerPos=self.view.mapToGlobal(self.horizontalHeader.pos()) pos=headerPos+QtCore.QPoint( 自水平收割台分段位置(logicalIndex), self.horizontalHeader.height(), ) action=self.menuValues.exec\uPOS 如果操作不是无: font=QtGui.QFont() 如果action.data()为None:#all self.proxy.setFilter(“,logicalIndex) 其他: font.setBold(真) self.proxy.setFilter(action.text(),logicalIndex) self.model.setFont(logicalIndex-1,字体) @QtCore.pyqtSlot(str) def on_lineEdit_textChanged(自我,文本): self.proxy.setFilter(文本,self.comboBox.currentIndex()+1) 如果名称=“\uuuuu main\uuuuuuuu”: 导入系统 app=qtwidts.QApplication(sys.argv)
#!/usr/bin/env python
#-*- coding:utf-8 -*-

from PyQt5 import QtCore, QtGui, QtWidgets
import pandas as pd

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())

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if not index.isValid():
            return QtCore.QVariant()

        return QtCore.QVariant(str(self._df.iloc[index.row(), index.column()]))

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        if hasattr(value, 'toPyObject'):
            # PyQt4 gets a QVariant
            value = value.toPyObject()
        else:
            # PySide gets an unicode
            dtype = self._df[col].dtype
            if dtype != object:
                value = None if value == '' else dtype.type(value)
        self._df.set_value(row, col, value)
        return True

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self._df.index)

    def columnCount(self, parent=QtCore.QModelIndex()):
        return len(self._df.columns)

    def sort(self, column, order):
        colname = self._df.columns.tolist()[column]
        self.layoutAboutToBeChanged.emit()
        self._df.sort_values(colname, ascending= order == QtCore.Qt.AscendingOrder, inplace=True)
        self._df.reset_index(inplace=True, drop=True)
        self.layoutChanged.emit()


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 CheckBoxDelegate(QtWidgets.QItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox cell of the column to which it's applied.
    """
    def __init__(self, parent):
        QtWidgets.QItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        """
        Important, otherwise an editor is created if the user clicks in this cell.
        """
        return None

    def paint(self, painter, option, index):
        """
        Paint a checkbox without the label.
        """
        self.drawCheck(painter, option, option.rect, QtCore.Qt.Unchecked if int(index.data()) == 0 else QtCore.Qt.Checked)

    def editorEvent(self, event, model, option, index):
        '''
        Change the data in the model and the state of the checkbox
        if the user presses the left mousebutton and this cell is editable. Otherwise do nothing.
        '''
        if not int(index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            return False

        if event.type() == QtCore.QEvent.MouseButtonRelease and event.button() == QtCore.Qt.LeftButton:
            # Change the checkbox-state
            self.setModelData(None, model, index)
            return True

        return False

    def setModelData (self, editor, model, index):
        '''
        The user wanted to change the old state in the opposite.
        '''
        model.setData(index, 1 if int(index.data()) == 0 else 0, QtCore.Qt.EditRole)

class TableView(QtWidgets.QTableView):
    """
    A simple table to demonstrate the QComboBox delegate.
    """
    def __init__(self, *args, **kwargs):
        QtWidgets.QTableView.__init__(self, *args, **kwargs)
        self.setItemDelegateForColumn(0, CheckBoxDelegate(self))

class myWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(myWindow, self).__init__(parent)
        self.centralwidget  = QtWidgets.QWidget(self)
        self.lineEdit       = QtWidgets.QLineEdit(self.centralwidget)
        self.view           = TableView(self)
        self.comboBox       = QtWidgets.QComboBox(self.centralwidget)
        self.label          = QtWidgets.QLabel(self.centralwidget)

        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1)
        self.gridLayout.addWidget(self.view, 1, 0, 1, 3)
        self.gridLayout.addWidget(self.comboBox, 0, 2, 1, 1)
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)

        self.setCentralWidget(self.centralwidget)
        self.label.setText("Regex Filter")

        self.load_sites()
        self.comboBox.addItems(["{0}".format(col) for col in self.model._df.columns])

        self.lineEdit.textChanged.connect(self.on_lineEdit_textChanged)
        self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged)

        self.horizontalHeader = self.view.horizontalHeader()
        self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked)


    def load_sites(self):
        df = pd.DataFrame({'site_codes': ['01', '02', '03', '04'],
                           'status': ['open', 'open', 'open', 'closed'],
                           'Location': ['east', 'north', 'south', 'east'],
                           'data_quality': ['poor', 'moderate', 'high', 'high']})

        self.model = PandasModel(df)
        self.proxy = CustomProxyModel(self)
        self.proxy.setSourceModel(self.model)
        self.view.setModel(self.proxy)
        self.view.resizeColumnsToContents()

        # delegate = CheckBoxDelegate(None)
        # self.view.setItemDelegateForColumn(0, delegate)



    @QtCore.pyqtSlot(int)
    def on_view_horizontalHeader_sectionClicked(self, logicalIndex):

        self.logicalIndex   = logicalIndex
        self.menuValues     = QtWidgets.QMenu(self)
        self.signalMapper   = QtCore.QSignalMapper(self)
        self.comboBox.blockSignals(True)
        self.comboBox.setCurrentIndex(self.logicalIndex)
        self.comboBox.blockSignals(True)

        valuesUnique = self.model._df.iloc[:, self.logicalIndex].unique()

        actionAll = QtWidgets.QAction("All", self)
        actionAll.triggered.connect(self.on_actionAll_triggered)
        self.menuValues.addAction(actionAll)
        self.menuValues.addSeparator()
        for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):
            action = QtWidgets.QAction(actionName, self)
            self.signalMapper.setMapping(action, actionNumber)
            action.triggered.connect(self.signalMapper.map)
            self.menuValues.addAction(action)
        self.signalMapper.mapped.connect(self.on_signalMapper_mapped)
        headerPos = self.view.mapToGlobal(self.horizontalHeader.pos())
        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(self.logicalIndex)

        self.menuValues.exec_(QtCore.QPoint(posX, posY))

    @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)

    @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)



if __name__ == "__main__":
    import sys
    app  = QtWidgets.QApplication(sys.argv)
    main = myWindow()
    main.show()
    main.resize(2000, 800)
    sys.exit(app.exec_())