代码之家  ›  专栏  ›  技术社区  ›  Jason

使用自定义HeaderView时PyQt5列排序不起作用

  •  1
  • Jason  · 技术社区  · 8 年前

    TableView 具有排序功能。如果我设置 反对我的习惯 HeaderView ,即使我的自定义 头视图 我们什么也没实现。 如果我用 的标题( hh=tv.horizontalHeader() )它排序。我做错什么了?

    代码如下:

    import sys
    import operator
    from PyQt5 import QtWidgets
    from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant
    
    class TableModel(QAbstractTableModel):
        def __init__(self, parent, datain, headerdata):
            super(TableModel,self).__init__(parent)
    
            self.arraydata=datain
            self.headerdata=headerdata
    
        def rowCount(self,p):
            return len(self.arraydata)
    
        def columnCount(self,p):
            if len(self.arraydata)>0:
                return len(self.arraydata[0])
            return 0
    
        def data(self, index, role):
            if not index.isValid():
                return QVariant()
            elif role != Qt.DisplayRole:
                return QVariant()
            return QVariant(self.arraydata[index.row()][index.column()])
    
        def headerData(self, col, orientation, role):
            if orientation==Qt.Horizontal and role==Qt.DisplayRole:
                return self.headerdata[col]
            return None
    
        def sort(self,col,order):
            self.layoutAboutToBeChanged.emit()
            self.arraydata=sorted(self.arraydata,key=operator.itemgetter(col))
            if order==Qt.DescendingOrder:
                self.arraydata.reverse()
            self.layoutChanged.emit()
    
    class MyHeaderView(QtWidgets.QHeaderView):
        def __init__(self,parent):
            super(MyHeaderView,self).__init__(Qt.Horizontal,parent)
    
    class MainFrame(QtWidgets.QWidget):
        def __init__(self):
            super(MainFrame,self).__init__()
            self.initUI()
    
        def initUI(self):
            self.doc_table=self.createTable()
            dummy_box=QtWidgets.QLineEdit()
            hlayout=QtWidgets.QHBoxLayout()
            h_split=QtWidgets.QSplitter(Qt.Horizontal)
            h_split.addWidget(self.doc_table)
            h_split.addWidget(dummy_box)
            hlayout.addWidget(h_split)
            self.setLayout(hlayout)
            self.show()
    
        def createTable(self):
            # create some dummy data
            self.tabledata=[['aaa' ,' title1', True, 1999],
                        ['bbb' ,' title2', True, 2000],
                        ['ccc' ,' title3', False, 2001]
                        ]
            header=['author', 'title', 'read', 'year']
            tablemodel=TableModel(self,self.tabledata,header)
    
            tv=QtWidgets.QTableView(self)
            tv.setModel(tablemodel)
    
            # Optional 1: use custom headerview, sorting not working
            #hh=MyHeaderView(tv)
            #tv.setHorizontalHeader(hh)
            # Optional 2: get tableview's header, sorting works
            hh=tv.horizontalHeader()
    
            tv.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
            tv.setShowGrid(True)
            hh.setSectionsMovable(True)
            hh.setStretchLastSection(False)
            hh.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
            tv.setSortingEnabled(True)
    
            return tv
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super(MainWindow,self).__init__()
            self.main_frame=MainFrame()
            self.setCentralWidget(self.main_frame)
            self.setGeometry(100,100,800,600)
            self.show()
    
    if __name__=='__main__':
        app=QtWidgets.QApplication(sys.argv)
        mainwindow=MainWindow()
        sys.exit(app.exec_())
    

    我的PyQt是5.9.2,通过conda安装

    1 回复  |  直到 6 年前
        1
  •  3
  •   eyllanesc    8 年前

    如果你检查一下 source code 在创建xxxHeaderView时,您会看到以下内容:

    ...
    QHeaderView *vertical = new QHeaderView(Qt::Vertical, q);
    vertical->setSectionsClickable(true);
    vertical->setHighlightSections(true);
    q->setVerticalHeader(vertical);
    
    QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q);
    horizontal->setSectionsClickable(true);
    horizontal->setHighlightSections(true);
    q->setHorizontalHeader(horizontal);
    ...
    

    所以缺少的是启用 setSectionsClickable() ,也可以添加 setHighlightSections(True) .

    def createTable(self):
        ...
    
        # Optional 1: use custom headerview, sorting not working
        hh =MyHeaderView(tv)
        tv.setHorizontalHeader(hh)
        # solution
        hh.setSectionsClickable(True) # <--- +++ 
        hh.setHighlightSections(True) # <--- +++
        # Optional 2: get tableview's header, sorting works
        # hh = tv.horizontalHeader()
    
        tv.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        tv.setShowGrid(True)
        hh.setSectionsMovable(True)
        hh.setStretchLastSection(False)
        hh.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        tv.setSortingEnabled(True)
        return tv