带有 setWordWrap(True) 的 QLabels 在放置在 QListWidget 中时不会垂直调整大小,即使 resizeMode 已设置为 Adjust 将尺寸政策设置为 Expanding使用 sizeHint 中的 QLabel 设置 QListWidgetItem 的大小提示

问题描述

如何将带有 QLabelsetWordWrap(True) 放在 QListWidget/QListView 中,以便 QLabel 在父小部件的大小是否已调整?

当我尝试这样做时,我遇到了 QLabels 没有获得正确高度的问题(参见下面的示例 2)

我正在使用

  • Python:3.8.5
  • PyQt5:5.15.2

示例 1:使用 QVBoxLayout

为了展示我想要完成的事情,我想首先展示一个示例,其中我只是将 QLabel 添加到 QVBoxLayout

这如我所愿:如果我水平调整(主)窗口的大小,带有换行文本的 QLabel 将垂直占用更多空间

example 1

import sys
from PyQt5.QtWidgets import *


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setMinimumHeight(150)
        self.main_widget = QWidget()
        self.setCentralWidget(self.main_widget)
        vbox = QVBoxLayout()
        self.main_widget.setLayout(vbox)

        label_1 = QLabel("label_1")
        vbox.addWidget(label_1)
        label_1.setStyleSheet("*{background-color: #f0f000;}")

        label_2 = QLabel("[wrapped] label_2 Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
        vbox.addWidget(label_2)
        label_2.setStyleSheet("*{background-color: #00f0f0;}")
        label_2.setWordWrap(True)


app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
app.exec_()

示例 2:使用 QListWidget

这是我遇到问题的代码:运行此代码不会为带有换行文本的 Qlabel 提供任何额外空间

(示例中使用了 QListWidget 而不是 QListView 但从我所看到的 - 以及我对这些类的理解 - 应该没有区别)

请注意,resizeMode property 已设置为 QListView.Adjust

example 2

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.list_widget = QListWidget()
        self.setCentralWidget(self.list_widget)
        self.list_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.list_widget.setResizeMode(QListView.Adjust)  # <-----
        self.list_widget.setUniformItemSizes(False)  # -should already be false,but just in case
        self.list_widget.setWordWrap(True)  # -AFAIK this should only effect text that is put directly into QListWidgetItems,but just in case

        item_1_text_str = f"Item number 1"
        lwi_item_1 = QListWidgetItem(self.list_widget)
        self.list_widget.addItem(lwi_item_1)
        item_1_widget_qlabel = QLabel(item_1_text_str)
        item_1_widget_qlabel.setStyleSheet("*{background-color: #f0f000;}")
        self.list_widget.setItemWidget(lwi_item_1,item_1_widget_qlabel)

        item_2_text_str = "[wrapped] label_2 Lorem ipsum dolor sit amet,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        lwi_item_2 = QListWidgetItem(self.list_widget)
        self.list_widget.addItem(lwi_item_2)
        item_widget_2_qlabel = QLabel(item_2_text_str)
        item_widget_2_qlabel.setWordWrap(True)  # <-------
        item_widget_2_qlabel.setStyleSheet("*{background-color: #00f0f0;}")
        self.list_widget.setItemWidget(lwi_item_2,item_widget_2_qlabel)


app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
app.exec_()

我尝试了什么

将尺寸政策设置为 Expanding

通常策略设置为 MinimumExpanding,所以我认为 Expanding 会更好,因为 Expanding 包含 Shrink 标志

在上面的代码示例 2 中,它看起来像这样:

    item_widget_2_qlabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)

这并没有帮助

使用 sizeHint 中的 QLabel 设置 QListWidgetItem 的大小提示

如果在 __init__ 中完成:

lwi_item_2.setSizeHint(item_widget_2_qlabel.sizeHint())

这样做的问题是它只会设置一次大小提示,然后sizeHint就会卡住,所以带回绕文本的QLabel无法垂直展开或收缩

或者使用此代码,以便在调整主窗口大小时更新 sizeHint:

class MainWindow(QMainWindow):
    [...]

def resizeEvent(self,a0: QResizeEvent) -> None:
    super().resizeEvent(a0)
    row = 0
    while row < self.list_widget.count():
        lwi_item = self.list_widget.item(row)
        item_widget = self.list_widget.itemWidget(lwi_item)
        widget_size_hint = item_widget.sizeHint()
        lwi_item.setSizeHint(widget_size_hint)  # <--------
        row += 1

令人惊讶的是,使用此代码时的结果是相同的:QLabel 的垂直大小没有改变

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)