spootnx spootnx - 6 months ago 101
Python Question

How to control QTableView's Header using QAbstractTableModel

Example below shows how 'My Column Name' header name is being centered from inside of the scope of

TableView
definition using:

self.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)


enter image description here

While this works I would like to know how to control
Header
from inside of QAbstractTableModel using its
headerData()
method.

As is the
headerData()
returns the header name:

if orientation==QtCore.Qt.Horizontal:
return QtCore.QVariant('My Column Name')


And it also returns a dummy
QtCore.QVariant()
if role!=QtCore.Qt.DisplayRole

if role!=QtCore.Qt.DisplayRole:
return QtCore.QVariant()


What other roles and values are available to be used with model's
headerData()
?

import sys, os
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)

class TableModel(QtCore.QAbstractTableModel):
def __init__(self):
QtCore.QAbstractTableModel.__init__(self)

self.items=['One','Two','Three','Four','Five','Six','Seven']

def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def columnCount(self, index=QtCore.QModelIndex()):
return 1

def data(self, index, role):
if not index.isValid() or not (0<=index.row()<len(self.items)):
return QtCore.QVariant()

item=str(self.items[index.row()])

if role==QtCore.Qt.UserRole:
return item

if role==QtCore.Qt.DisplayRole:
return item

if role==QtCore.Qt.TextColorRole:
return QtCore.QVariant(QtGui.QColor(QtCore.Qt.white))

if role == QtCore.Qt.BackgroundRole:
if index.row()%2:
return QtCore.QVariant(QtGui.QColor("#242424"))
else:
return QtCore.QVariant(QtGui.QColor(QtCore.Qt.black))

def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole):
if role!=QtCore.Qt.DisplayRole:
return QtCore.QVariant()
if orientation==QtCore.Qt.Horizontal:
return QtCore.QVariant('My Column Name')

class TableView(QtGui.QTableView):
def __init__(self, parent=None):
super(TableView, self).__init__(parent)

self.setBackgroundRole(QtGui.QPalette.Base)
p=self.palette()
p.setColor(self.backgroundRole(), QtGui.QColor((QtCore.Qt.black)))
self.setPalette(p)

self.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
self.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)

font=QtGui.QFont()
font.setPointSize(9)
self.horizontalHeader().setFont(font)

myModel=TableModel()
self.setModel(myModel)


view=TableView()
view.show()
sys.exit(app.exec_())

Answer

Headers for table views are provided by QHeaderView. The doc describes which data roles are supported by it:

QHeaderView respects the following item data roles: TextAlignmentRole, DisplayRole, FontRole, DecorationRole, ForegroundRole, and BackgroundRole.

Here is an example of a headerData implementation (code is in C++):

QVariant
Model::headerData(int section, Qt::Orientation orientation, int role) const
{
    ...
    if (role == Qt::DisplayRole)
    {
        return QString("Header #%1").arg(section);
    }

    if (role == Qt::FontRole)
    {
        QFont serifFont("Times", 10, QFont::Bold, true);
        return serifFont;
    }

    if (role == Qt::TextAlignmentRole)
    {
        return Qt::AlignRight;
    }

    if (role == Qt::BackgroundRole)
    {
        return QBrush(Qt::blue);
    }

    if (role == Qt::ForegroundRole)
    {
        return QBrush(Qt::red);
    }
    ...
}

Also it must be noted that BackgroundRole most likely will be overriden by a widget palette and a general application style. You can check this answer about this.

Comments