python - 如何重新排列 QTableView 的列顺序

标签 python qt pyqt qtableview

下面的代码创建了一个由 Model/Proxy 框架驱动的 QTableView。

source-model 中声明的 self.headerNames 列表变量存储标题列的名称。此列表中的名称数由同一 源模型columnCount() 方法用于返回 View 中的列数:

def columnCount(self, parent=QModelIndex()):
    return len(self.headerNames)

Proxy 模型的 headerData() 通过 source model 访问这个 self.headerNames 变量:

sourceModel=self.sourceModel()

if role==Qt.DisplayRole 上,Proxy 检索列的名称并将其返回给 QTableView:

return QVariant( sourceModel.headerNames[column] )

有一个右键单击菜单实现在标题栏右键单击。 那部分工作正常。但是由于我找不到任何关于其他人如何做的例子,我不得不自己设计它的工作方式。如果您发现它可以改进,我将不胜感激。

我接下来要实现的是能够以任意顺序重新排列列。但我不确定从哪里开始。

enter image description here

附言请忽略 QTableView 中显示的项目的名称。 我想让代码尽可能简单,只在此处关注标题/列主题。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = ['Item_A_001','Item_A_002','Item_B_001','Item_B_002']
        self.headerNames=['Column 0','Column 1','Column 2','Column 3','Column 4','Column 5','Column 6','Column 7']

    def rowCount(self, parent=QModelIndex()):
        return len(self.items)       
    def columnCount(self, parent=QModelIndex()):
        return len(self.headerNames)

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

        row=index.row()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

class Proxy(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy, self).__init__()

    def filterAcceptsRow(self, row, parent):
        return True

    def headerData(self, column, orientation, role=Qt.DisplayRole):
        sourceModel=self.sourceModel()

        if role==Qt.TextAlignmentRole:
            if orientation==Qt.Horizontal:
                return QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
            return QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))

        if role==Qt.DisplayRole:
            if orientation==Qt.Horizontal:
                return QVariant( sourceModel.headerNames[column] )
            else:
                return QVariant()
        else:
            return QVariant()

        return QVariant(int(column+1))


class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        tableModel=Model(self)               

        proxyModel=Proxy()
        proxyModel.setSourceModel(tableModel)

        self.tableview=QTableView(self) 
        self.tableview.setModel(proxyModel)
        self.tableview.horizontalHeader().setStretchLastSection(True)
        self.tableview.setSelectionMode(QAbstractItemView.MultiSelection)

        header=self.tableview.horizontalHeader()
        header.setContextMenuPolicy(Qt.CustomContextMenu)
        header.connect(header, SIGNAL("customContextMenuRequested(QPoint)" ), self.headerRightClicked)

        self.resHeaderMenu=QMenu(self)

        for column in range(proxyModel.columnCount()):
            columnName=proxyModel.headerData(column, Qt.Horizontal).toPyObject()
            actn=QAction('%s'%columnName, self.resHeaderMenu, checkable=True)
            actn.setChecked(True)
            actn.triggered.connect(self.resHeaderMenuTriggered)
            self.resHeaderMenu.addAction(actn)

        layout = QVBoxLayout(self)
        layout.addWidget(self.tableview)
        self.setLayout(layout)

    def headerRightClicked(self, QPos):
        parentPosition=self.tableview.mapToGlobal(QPoint(0, 0))        
        menuPosition=parentPosition + QPos
        self.resHeaderMenu.move(menuPosition)
        self.resHeaderMenu.show()        

    def resHeaderMenuTriggered(self, arg):
        print 'resHeaderMenuTriggered', arg
        for i, actn in enumerate(self.resHeaderMenu.actions()):
            if not actn.isChecked():
                self.tableview.setColumnHidden(i, True) 

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

最佳答案

如果您真的想自己重新排列列:

您可以通过 moveSection 移动或交换部分和 swapSections horizo​​ntalHeader 的方法。

headerView.moveSection(x, y)

将移动 x 列,使其成为 y 列,而

headerView.swapSections(x,y)

将 - 显然 - 交换两列的位置。

关于python - 如何重新排列 QTableView 的列顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28074194/

相关文章:

qt - PyQt:如何设置 QTreeView 的行高

python - 在 PyQt5 中对齐弹出窗口小部件

python - 打开pyxl "Numbers Stored as Text"

python - 使用 Tkinter 的“pip install Module”程序

c++ - 在 C++ 中使用 qt 显示工具栏中图标的状态

python - "GUI becomes unresponsive after clicking the button"

python - 了解碰撞列表中哪个矩形发生了碰撞

python - 这段代码有什么问题?

qt - QML 圆规

c++ - 在 TreeView 中进行 "tracking"项选择的最简单方法?