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

标签 python pyqt pyqt5 qtableview qheaderview

我正在尝试创建一个具有排序功能的TableView。如果我将 TableView 对象设置为我的自定义 HeaderView,则单击标题将不会排序,即使我的自定义 HeaderView 没有重新实现任何内容。 如果我使用 TableView 的 header (hh=tv.horizo​​ntalHeader()) 进行排序。我做错了什么?

代码如下:

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安装

最佳答案

如果您检查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

关于python - 使用自定义 HeaderView 时列排序不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52332534/

相关文章:

python - 无法启动设计的pyQt应用程序

Python:如何使用 PyQt 调整光栅图像的大小

dialog - PyQt:如何创建一个对话框作为另一个对话框的子项

python - 将文件从文件夹移动到文件夹 python 时遇到问题

python - 如何让python一次识别多个字母

python - 在 PyQt 中,如何将终端嵌入到窗口中?

python - PyQt5 使用内存中的 QLabel 显示图像

python - PyQt 访问动态创建的 Label 和 LineEdit

python - 如何根据multiIndex DataFrame的内部索引进行操作?

python - 无法在discord.py中对字典进行排序