如何重新安排QTableView的列顺序

alp*_*ric 3 python qt pyqt qtableview

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

self.headerNamessource-model存储中声明的列表变量是Header列的名称.名称的此列表中的号码用于通过相同source modelcolumnCount()方法,以返回在视图中柱的数目:

def columnCount(self, parent=QModelIndex()):
    return len(self.headerNames)
Run Code Online (Sandbox Code Playgroud)

Proxy型号的headerData()上网本self.headerNames通过变量source model:

sourceModel=self.sourceModel()
Run Code Online (Sandbox Code Playgroud)

if role==Qt.DisplayRole代理上检索并返回列的名称到QTableView:

return QVariant( sourceModel.headerNames[column] )
Run Code Online (Sandbox Code Playgroud)

右键单击标题列上实现了右键单击菜单.那部分工作正常.但由于我找不到其他人如何做的例子,我不得不设计自己如何运作.如果你发现它可以改进,我将不胜感激.

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

在此输入图像描述

Ps请忽略QTableView中显示的项目名称.我希望尽可能简化代码,只关注Header/Column主题.

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_())
Run Code Online (Sandbox Code Playgroud)

seb*_*ian 6

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

您可以通过moveSectionswapSections方法移动或交换部分horizontalHeader.

headerView.moveSection(x, y)
Run Code Online (Sandbox Code Playgroud)

将移动列x,使得它的列y之后,而

headerView.swapSections(x,y)
Run Code Online (Sandbox Code Playgroud)

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