QTreeView 中的列对齐 | PyQt5

Column Alignment in QTreeView | PyQt5

如何水平对齐 QTreeView 的一列(该列的所有项目)?我正在使用 QStandardItemModel()。我已经搜索过,但没有找到任何相关文档。 提前致谢!

注意:建议的解决方案仅适用于 OP 要求的基本情况(简单的 QStandardItemModel 或提供基本模型数据显示的任何子类模型);在这个答案的底部阅读更多内容

您可以子类化模型并重写 data() 函数,以便在请求 Qt.TextAlignmentRole 时 return 适当的 Qt.AlignmentFlag,默认情况下,它是None 除非用 setData()item.setTextAlignment() 手动设置:当 returned 值为 None 时,对齐方式由 view,通常基于系统的布局方向。

在下面的示例中,您可以为任何列(或使用 None 恢复它)设置任意 default 对齐方式,除非对齐方式有已明确设置为如上所述。

class AlignModel(QtGui.QStandardItemModel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.columnAlignments = {}

    def setColumnAlignment(self, column, alignment):
        if alignment:
            self.columnAlignments[column] = alignment
        elif column in self.columnAlignments:
            self.columnAlignments.pop(column)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.TextAlignmentRole:
            return (super().data(index, role) or 
                self.columnAlignments.get(index.column()))
        return super().data(index, role)

# set the center alignment for the *second* column:
model = AlignModel()
model.setColumnAlignment(1, QtCore.Qt.AlignCenter)

请注意,Qt.AlignCenter 意味着 Qt.AlignVCenterQt.AlignHCenter(通过 OR 运算符),因此如果要向右或向左对齐,还必须提供垂直对齐:例如,Qt.AlignRight|Qt.AlignVCenter.

一些重要说明:

作为 ,常见的建议是使用委托而不是对模型进行子类化。虽然我的解决方案适用于需要非常简单的解决方案(并且可以实际使用模型,但更高级别 类、QTreeWidget、QTableWidget 和 QListWidget 并非如此)的情况,但一般规则是模型应该 never return “更改”内容:来自 data() 的 returned 值应该始终反映索引的实际内容,并且任何修改(包括显示文本对齐等数据)应该使用代理模型或通过更改委托的行为来进行。
从 OOP 的典型模块化观点来看,这是非常重要的,特别是考虑到 MVC(或 MV,对于 Qt)模式:模型(真实 数据)和视图(如何显示数据)应该是不同的和独立的。

以这种情况为例:文本对齐。让我们假设对齐应该朝向第一列的“开始”:对于从右到左的语言,这意味着将文本对齐在右边(因为第一列在右边缘);如果模型要被序列化,结果是对齐将依赖于序列化的 source 布局,而对齐应该完全依赖于用户查看的布局(反序列化)它。
所以,这就是您应该问的问题:文本对齐对于模型(例如,数据可能包含具有不同书写方向的各种语言的文本)或视图重要吗?如果这些都不重要,那么你必须考虑什么是最好的解决方案,性能方面:例如,如果你要有一个非常大的模型(有数千个条目,可能有数百个项目)同时显示),并且您确定某个列将始终具有相同的对齐方式,那么您可以覆盖 data() 或使用 QIdentityProxyModel,这肯定比使用委托和覆盖更快paint 方法。
在任何其他情况下,委托解决方案是更正确和连贯的解决方案,因为它还允许以不同方式显示相同的模型数据,无论内容是什么。

不涉及从模型继承的解决方案(这有时是一个限制,例如 QListWidget、QTableWidget 或 QTreeWidget)是:

  • 使用代理模型(例如 QIdentityProxyModel)。
  • 使用代表。

在这种情况下,我将使用最后一种解决方案:

from functools import cached_property


class AlignmentDelegate(QStyledItemDelegate):
    @cached_property
    def alignment(self):
        return dict()

    def set_column_alignment(self, column, alignment):
        self.alignment[column] = alignment

    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        alignment = self.alignment.get(index.column(), None)
        if alignment is not None:
            option.displayAlignment = alignment
delegate = AlignmentDelegate(self.view)
self.view.setItemDelegate(delegate)
delegate.set_column_alignment(1, QtCore.Qt.AlignCenter)

前一种方法的优点是可以适用于任何模型,修改方便