Green Cell
Green Cell

Reputation: 4777

align pixmap in column's center with QTreeView and QAbstractItemModel

How do I make a pixmap's alignment centered to its column in a QTreeView? I have 2 columns with icons that are aligned to left, but I want one of them centered, so this needs to work on a single column and not force the whole table to one alignment.

I'm using a QTreeView with QAbstractItemModel as its model. On one column I flagged it as QtCore.Qt.DecorationRole and return a pixmap in the model's data() method so that it displays images along that column.

All works well, except that the images all align left, and for the life of me I can't get them centered horizontally.

In the data() method, I tried returning QtCore.Qt.AlignCenter if the role was QtCore.Qt.TextAlignmentRole, but that seems to only effect text (duh!).

Is there another way to achieve this? I'm not interested in taking the route of delegates if possible.

Upvotes: 2

Views: 1310

Answers (1)

eyllanesc
eyllanesc

Reputation: 243973

A possible solution is to overwrite the delegate's initStyleOption() method:

from PySide2 import QtCore, QtGui, QtWidgets


class IconCenterDelegate(QtWidgets.QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super(IconCenterDelegate, self).initStyleOption(option, index)
        option.decorationAlignment = (
            QtCore.Qt.AlignHCenter | QtCore.Qt.AlignCenter
        )
        option.decorationPosition = QtWidgets.QStyleOptionViewItem.Top


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QTreeView()
    model = QtGui.QStandardItemModel(w)
    w.setModel(model)
    delegate = IconCenterDelegate(w)
    w.setItemDelegateForColumn(1, delegate)
    icons = [
        "SP_TitleBarMinButton",
        "SP_TitleBarMenuButton",
        "SP_TitleBarMaxButton",
        "SP_TitleBarCloseButton",
        "SP_TitleBarNormalButton",
        "SP_TitleBarShadeButton",
        "SP_TitleBarUnshadeButton",
        "SP_TitleBarContextHelpButton",
        "SP_MessageBoxInformation",
        "SP_MessageBoxWarning",
        "SP_MessageBoxCritical",
        "SP_MessageBoxQuestion",
        "SP_DesktopIcon",
    ]
    parent = model.invisibleRootItem()
    for icon_name in icons:
        icon = QtWidgets.QApplication.style().standardIcon(
            getattr(QtWidgets.QStyle, icon_name)
        )
        its = []
        for _ in range(3):
            it = QtGui.QStandardItem()
            it.setIcon(icon)
            its.append(it)
        parent.appendRow(its)
    model.appendRow(it)
    w.resize(640, 480)
    w.expandAll()
    w.show()
    sys.exit(app.exec_())

enter image description here


If you want the icons of all the columns to be aligned centrally then you could overwrite the viewOptions() method of the view:

class TreeView(QtWidgets.QTreeView):
    def viewOptions(self):
        option = super().viewOptions()
        option.decorationAlignment = (
            QtCore.Qt.AlignHCenter | QtCore.Qt.AlignCenter
        )
        option.decorationPosition = QtWidgets.QStyleOptionViewItem.Top
        return option

Upvotes: 3

Related Questions