【问题标题】:Column Alignment in QTreeView | PyQt5QTreeView 中的列对齐 | PyQt5
【发布时间】:2021-05-29 14:56:08
【问题描述】:

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

【问题讨论】:

  • 您的意思是要水平对齐该列的每个项目的内容?您在视图上使用什么模型?
  • 我相应地编辑了我的问题。感谢您的回复!

标签: python python-3.x pyqt pyqt5


【解决方案1】:

不涉及从模型继承(有时是 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)

前一种方法的优点是可以应用于任何模型,并且易于修改。

【讨论】:

    【解决方案2】:

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

    您可以对模型进行子类化并覆盖data() 函数,以便在请求Qt.TextAlignmentRole 时返回正确的Qt.AlignmentFlag,默认情况下为无,除非使用setData()item.setTextAlignment() 手动设置:当返回值为None时,对齐方式由view决定,一般以系统布局方向为准。

    在下面的示例中,您可以为任何列设置任意的默认对齐方式(或使用None 来恢复它),除非已按照上述方式明确设置对齐方式,否则将使用该对齐方式。

    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 运算符),因此如果要向右或向左对齐,还必须提供垂直对齐方式:例如,@987654333 @。

    一些重要说明:

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

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

    【讨论】:

    • 虽然你的更新很有趣,但我不同意:我们将什么定义为数据或模型?好吧,基本信息可能会或可能不会涵盖文本的对齐方式。所以这是基于意见。例如,我们举个例子:应该用逗号还是句号来分隔整数部分和小数部分?好吧,数据(模型)不应该有这些信息,但是从语言环境中获取信息的视图应该有。
    • 正如您在最后一行中指出的那样:委托用于使用相同的模型自定义视图(无需修改它),从我的角度来看,文本对齐实现了该功能。
    • 代理模型也是一种尝试,即修改它提供的信息但不修改基础信息(背景模型)。
    • @eyllanesc 我完全同意(我应该尝试改写我更新的部分内容)。我试图解释的是: 1. 在许多情况下,模型只是简单直接的数据可视化,不会真正以任何其他方式使用(可能使用 QTreeWidget 的情况) ,但需要更高级的功能); 2. 文本对齐可以是“视图”的一部分(至少在某种程度上,视情况而定),就像它在模型内容中可能很重要一样; 3. 1+2+性能:一旦完全控制(和意识!)模型,->
    • 难道不是同样的逻辑也适用于用 python 编写的模型吗?如果您想获得与 C++ 相同的效率,请使用 C++。 PyQt 和 PySide 作为 Qt 包装器,也有这些区别。
    猜你喜欢
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2014-10-27
    • 2018-04-16
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    相关资源
    最近更新 更多