Word Wrapped QLabel 提前切断文本 [英] Word Wrapped QLabel cutting off text early

查看:60
本文介绍了Word Wrapped QLabel 提前切断文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm essentially trying to just add a title to the top of a layout to give a brief description, but Qt has to get in the way already.

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

I have word wrap enabled, and the QLabel will grow it's height dynamically based on how long the content is... but it's always too short.

我的代码:

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_()

推荐答案

我想补充一些关于这个特定问题的见解.

I'd like to add some insight about this specific issue.

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

There are various reasons for this behavior, with the most important being layout issues when using child widgets that have rich text (to clarify, even if you're not using rich text, enabling word wrapping on a QLabel makes its contents rich text internally). This is explained in the layout documentation:

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

The use of rich text in a label widget can introduce some problems to the layout of its parent widget. Problems occur due to the way rich text is handled by Qt's layout managers when the label is word wrapped.

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

Consider that the computation of a size hint for a rich text content is quite complex, and with QLabels it often results in multiple recursive calls between the layouts and the label. While all that happens quite immediately and transparently to the user, this is sometimes prone to unexpected behavior, and the result is that the QLabel is not able to correctly compute its size under certain conditions.

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

Note that in normal conditions one would add a label and set the alignment on the label, not on the layout.

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

Before explaining further, an important consideration: layout management under Qt works using an abstract item called QLayoutItem, which works as a "reference" for anything that can be managed by a layout. When you add a widget to a layout, Qt actually creates a new QLayoutItem for that widget, and it's that item that is added to the layout; the same happens when adding a layout. But, wait: all Qt layouts are subclasses of QLayout, which actually inherits QLayoutItem!

当您使用简单的 addWidget(someWidget) 时,该小部件将尝试使用整个单元格";布局提供,但当指定对齐方式时 (addWidget(someWidget,alignment=Qt.AlignmentFlag)),小部件只会扩展到其大小提示.

When you use the simple addWidget(someWidget), that widget will try to use the entire "cell" the layout provides, but when an alignment is specified (addWidget(someWidget, alignment=Qt.AlignmentFlag)) the widget will only expand to its size hint.

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

In your case, the problem is due to the fact that you have set the alignment on the layout "item" (the vertical box layout), which is the same as specifying an alignment when adding an item to a layout, as written above. In this case, the layout [item] will use its size hint, but due to the aforementioned issues with rich text, this doesn't work very well. Generally speaking, you should almost never set the alignment of the layout.

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

Normally one would simply add the label to the layout and specify the alignment on the label, but this clearly won't work in your case: the label will correctly align the text on top, but will also still try to occupy the whole available cell space, and since you're also setting a background you'll see the color for the whole available space.

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

While you can use addStretch() after adding the label, this might be a slight problem whenever you need to add other widgets: the new widget will be added after the stretch, leaving blank space between the label and the new widget. In that case, the only solution is to always use insertWidget with an index based on the item count:

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

这可行,但不是很舒服,并且降低了代码的可读性.

That works, but it's not very comfortable and makes the code less readable.

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

The simplest solution is to specify the alignment when adding the label and not on the layout:

        # 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 代替.

Finally, adjustSize() only works for widgets not added to a layout or top level widgets (windows); since you're going to add the widget to a layout, that call is useless.
Also, instead of using the QBoxLayout(orientation) constructor, it's usually better to use the direct classes QHBoxLayout and QVBoxLayout instead.

这篇关于Word Wrapped QLabel 提前切断文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆