0

我本质上只是想在布局的顶部添加一个标题来给出一个简短的描述,但 Qt 已经妨碍了。

我启用了自动换行,并且QLabel 根据内容的长度动态增加它的高度......但它总是太短。

图像显示截断的文本

我的代码:

class Window(QMainWindow):

    def __init__(self, qtpy):
        super().__init__()
        self.qtpy = qtpy
        self.setMinimumSize(250, 150)
        self.resize(600, 450)

class ThemeTool(Window):

    def __init__(self, qtpy):
        super().__init__(qtpy)
        self.setWindowTitle("qtpy-rant Theme Tool")

        widget = QWidget()
        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        sidebar = QWidget()
        sidebar.setMaximumWidth(150)
        sidebar_layout = QBoxLayout(QBoxLayout.TopToBottom)
        sidebar_layout.setAlignment(Qt.AlignTop)
        sidebar.setLayout(sidebar_layout)
        layout.addWidget(sidebar)

        palette = sidebar.palette()
        sidebar.setAutoFillBackground(True)
        palette.setColor(sidebar.backgroundRole(), QColor("#e3e3e3"))
        sidebar.setPalette(palette)

        sidebar_label = QLabel()
        sidebar_label.setWordWrap(True)
        sidebar_label.setText("The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors The Theme Tool is used to preview a theme and detect errors")
        sidebar_label.adjustSize()
        sidebar_layout.addWidget(sidebar_label)

        palette = sidebar_label.palette()
        sidebar_label.setAutoFillBackground(True)
        palette.setColor(sidebar_label.backgroundRole(), QColor("#ff0000"))
        sidebar_label.setPalette(palette)

        theme_area = QWidget()
        theme_area_layout = QBoxLayout(QBoxLayout.TopToBottom)
        theme_area.setLayout(theme_area_layout)
        layout.addWidget(theme_area, 1)

qapplication = QApplication(sys.argv)
main_window = ThemeTool(None)
main_window.show()
qapplication.exec_()
4

1 回答 1

2

我想就这个特定问题添加一些见解。

这种行为有多种原因,最重要的是使用具有富文本的子小部件时的布局问题(澄清一下,即使您不使用富文本,在 QLabel 上启用自动换行使其内容在内部成为富文本) . 这在布局文档中进行了解释:

在标签小部件中使用富文本可能会给其父小部件的布局带来一些问题。当标签是自动换行时,Qt 的布局管理器处理富文本的方式会出现问题。

考虑到富文本内容的大小提示的计算非常复杂,并且使用 QLabels 它通常会导致布局和标签之间的多次递归调用。虽然所有这些对用户来说都是非常直接和透明的,但这有时容易出现意外行为,结果是 QLabel 在某些条件下无法正确计算其大小。

请注意,在正常情况下,人们会添加一个标签并在标签上设置对齐方式,而不是在布局上。

在进一步解释之前,一个重要的考虑因素:Qt 下的布局管理使用一个名为QLayoutItem的抽象项目,它作为任何可以由布局管理的东西的“参考”。当您将一个小部件添加到布局时,Qt 实际上为该小部件创建了一个新的 QLayoutItem,而正是项目被添加到布局中;添加布局时也会发生同样的情况。但是,等等:所有 Qt 布局都是 QLayout 的子类,它实际上继承了 QLayoutItem!

当您使用 simpleaddWidget(someWidget)时,该小部件将尝试使用布局提供的整个“单元格”,但当指定对齐 ( addWidget(someWidget, alignment=Qt.AlignmentFlag)) 时,该小部件将仅扩展到其大小提示。

在您的情况下,问题是由于您在布局“项目”(垂直框布局)上设置了对齐方式,这与在将项目添加到布局时指定对齐方式相同,如上所述。在这种情况下,布局 [item] 将使用其大小提示,但由于上述富文本的问题,这不能很好地工作。一般来说,您几乎不应该设置布局的对齐方式。

通常,只需将标签添加到布局并在标签上指定对齐方式,但这显然不适用于您的情况:标签将正确对齐顶部的文本,但仍会尝试占据整个可用单元格空间,并且由于您还设置了背景,您将看到整个可用空间的颜色。

虽然您可以addStretch()在添加标签后使用,但当您需要添加其他小部件时,这可能是一个小问题:新小部件将在拉伸后添加在标签和新小部件之间留下空白空间。在这种情况下,唯一的解决方案是始终使用带有基于项目计数的索引的 insertWidget:

        sidebar_layout.insertWidget(sidebar_layout.count() - 1, newWidget)

这行得通,但它不是很舒服,并且使代码的可读性降低。

最简单的解决方案是在添加标签时而不是在布局上指定对齐方式:

        # remove the following
        # sidebar_layout.setAlignment(Qt.AlignTop)
        # ...
        sidebar_label = QLabel()
        sidebar_label.setWordWrap(True)
        sidebar_label.setText("")
        # this is also unnecessary
        # sidebar_label.adjustSize()
        sidebar_layout.addWidget(sidebar_label, alignment=Qt.AlignTop)

最后,adjustSize()仅适用于未添加到布局或顶级小部件(窗口)的小部件;由于您要将小部件添加到布局中,因此该调用是无用的。
此外,与其使用QBoxLayout(orientation)构造函数,不如使用直接类QHBoxLayoutQVBoxLayout来代替。

于 2020-10-02T12:28:17.107 回答