Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to re-arrange QTableView's Columns Order

The code below creates a single QTableView driven by Model/Proxy framework.

The self.headerNames list-variable declared in source-model stores the names of the Header's Columns. The number of names in this list is used by the same source model's columnCount() method to return the number of column in a view:

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

The Proxy model's headerData() access this self.headerNames variable via source model:

sourceModel=self.sourceModel()

On if role==Qt.DisplayRole the Proxy retrieves and returns the name of the column to QTableView:

return QVariant( sourceModel.headerNames[column] )

There is a right-click menu implemented on header-column right-click. That portion is working fine. But since I could not find any examples on how others do it I had to design how it would work myself. I would appreciate if you find it could be improved.

What I want to implement next is the ability to re-arrange the column in arbitrary order. But I am not sure where to start.

enter image description here

P.s. Please disregard the names of the Items displayed in QTableView. I wanted to keep the code as simple as possible focusing on Header/Column subject only here.

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_())
like image 254
alphanumeric Avatar asked Jan 21 '15 18:01

alphanumeric


People also ask

How do I change the order of columns in a table?

In Object Explorer, right-click the table with columns you want to reorder and select Design. Select the box to the left of the column name that you want to reorder. Drag the column to another location within the table.

Does the order of columns in a table matter?

Yes, column order does matter.


1 Answers

In case you really want to re-arrange the columns yourself:

You can move or swap sections via the moveSection and swapSections methods of the horizontalHeader.

headerView.moveSection(x, y)

will move column x such that it's column y afterwards, while

headerView.swapSections(x,y)

will - obviously - swap the positions of the two columns.

like image 162
sebastian Avatar answered Sep 23 '22 08:09

sebastian