You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide2 QListWidgetItem自定义部件窗口Resize时高度不收缩问题修复

QListWidget自定义部件随窗口调整自动适配高度的解决方案

问题场景

使用PySide2开发时,为QListWidget添加自定义部件后,主对话框调整大小,QListWidgetItem无法自动调整高度以适配可用空间,出现大量空白间隙。

问题效果对比图

解决方法

问题核心是QListWidgetItem的sizeHint不会随自定义部件宽度变化自动更新,需通过以下调整实现动态适配:

1. 改造自定义部件NoteWidget

  • 移除self.uiDescription.adjustSize(),避免固定描述标签高度
  • 重写resizeEvent,在部件宽度变化时重新计算布局,并发送自定义信号通知列表项更新尺寸
  • 调整布局约束为SetMinAndMaxSize,允许部件根据内容动态调整大小

2. 监听QListWidget宽度变化

在主窗口中,监听QListWidget的尺寸变化事件,遍历所有列表项,触发自定义部件重新计算尺寸并更新item的sizeHint

修改后的完整代码

import os
import sys
from PySide2 import QtCore, QtGui, QtWidgets


class NoteWidget(QtWidgets.QWidget):
    sizeChanged = QtCore.Signal()  # 自定义尺寸变化信号

    def __init__(self, noteItem):
        super(NoteWidget, self).__init__()
        self.setStyleSheet('border: 1px solid red;')

        # 控件初始化
        self.uiCategory = QtWidgets.QLabel()
        self.uiCategory.setTextFormat(QtCore.Qt.PlainText)
        self.uiCategory.setStyleSheet('font-family: Arial; font-weight: bold; font-size: 14px;')
        self.uiCategory.setText(noteItem['category'])

        self.uiDescription = QtWidgets.QLabel()
        self.uiDescription.setWordWrap(True)
        self.uiDescription.setText(noteItem['description'])

        # 布局设置
        self.mainLayout = QtWidgets.QVBoxLayout()
        self.mainLayout.setContentsMargins(10,10,10,10)
        self.mainLayout.setSpacing(0)
        self.mainLayout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
        self.mainLayout.setAlignment(QtCore.Qt.AlignTop)
        
        self.mainLayout.addWidget(self.uiCategory)
        self.mainLayout.addWidget(self.uiDescription)
        self.setLayout(self.mainLayout)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.mainLayout.invalidate()  # 强制布局重新计算
        self.sizeChanged.emit()  # 发送尺寸变化信号


class FileNotesDialog(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super(FileNotesDialog, self).__init__(parent)

        self.uiList = QtWidgets.QListWidget()
        self.uiList.setSpacing(0)
        self.uiList.setFocusPolicy(QtCore.Qt.NoFocus)
        self.uiList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
        self.uiList.verticalScrollBar().setSingleStep(10)
        self.uiList.setUniformItemSizes(False)
        self.uiList.setResizeMode(QtWidgets.QListWidget.Adjust)
        self.uiList.setSizeAdjustPolicy(QtWidgets.QListWidget.AdjustToContents)
        self.uiList.setSelectionMode(QtWidgets.QListView.ExtendedSelection)

        self.mainLayout = QtWidgets.QVBoxLayout()
        self.mainLayout.setSpacing(6)
        self.mainLayout.setContentsMargins(6, 6, 6, 6)
        self.mainLayout.addWidget(self.uiList)

        self.mainWidget = QtWidgets.QWidget()
        self.mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.mainWidget)

        self.populateNotes()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.updateListItemSizes()  # 窗口调整时更新所有列表项尺寸

    def updateListItemSizes(self):
        for index in range(self.uiList.count()):
            item = self.uiList.item(index)
            widget = self.uiList.itemWidget(item)
            if widget:
                widget.adjustSize()
                item.setSizeHint(widget.sizeHint())

    def populateNotes(self):
        self.uiList.clear()
        notes = [
            {'category': 'Misc', 'description': 'Here is a simple reminder'},
            {'category': 'Today', 'description': 'Here is a longer reminder that will use wordwrap because it is a really long description provided by the user for reading when they have time. It should not be ignored.'},
            {'category': 'Notes', 'description': 'Here is another simple reminder for you.'},
            {'category': 'General', 'description': 'I think this will fix the problem if you have to time implement this when you are working today.'}
        ]

        for obj in notes:
            nw = NoteWidget(obj)
            lwi = QtWidgets.QListWidgetItem()
            self.uiList.addItem(lwi)
            self.uiList.setItemWidget(lwi, nw)
            # 连接尺寸变化信号,实时更新item尺寸
            nw.sizeChanged.connect(lambda item=lwi, widget=nw: item.setSizeHint(widget.sizeHint()))
            lwi.setSizeHint(nw.sizeHint())


def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = FileNotesDialog()
    ex.resize(500,700)
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

关键改动说明

  • NoteWidget中添加sizeChanged信号,确保宽度变化时实时通知列表项更新尺寸
  • 移除固定高度的adjustSize()调用,让描述标签随宽度自动换行调整高度
  • 主窗口监听resize事件,批量更新所有列表项的尺寸
  • 将QListWidget的sizeAdjustPolicy改为AdjustToContents,确保列表自身适配内容变化

内容的提问来源于stack exchange,提问作者JokerMartini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 07:36:23