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

QListView图标模式搭配QFileSystemModel如何实现项目文本自动换行?

解决方法

问题原因

  • 你开启了setUniformItemSizes(True),该配置会强制所有列表项使用相同尺寸,忽略每个项的独立高度计算,导致换行后的文本高度无法被正确识别
  • 固定设置了GridSize高度为80,当图标+换行后文本的总高度超过80时,文本自然会被截断

实现步骤

  1. 自定义支持自动换行计算的QStyledItemDelegate,重写尺寸计算和绘制逻辑
  2. 移除原有错误配置,为ListView设置自定义委托

完整可运行代码

import sys

from PySide2 import QtCore
from PySide2 import QtWidgets


class WrapTextDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None, max_text_width=80):
        super().__init__(parent)
        # 每个列表项的文本最大宽度,可根据需求调整
        self.max_text_width = max_text_width
        # 图标尺寸,和ListView设置的iconSize保持一致即可
        self.icon_size = QtCore.QSize(48, 48)
        # 图标和文本的间距
        self.spacing = 4

    def sizeHint(self, option, index):
        # 计算文本换行后的实际高度
        text = index.data(QtCore.Qt.DisplayRole)
        text_rect = option.fontMetrics.boundingRect(
            QtCore.QRect(0, 0, self.max_text_width, 9999),
            QtCore.Qt.TextWordWrap | QtCore.Qt.AlignHCenter,
            text
        )
        # 总高度 = 图标高度 + 间距 + 文本高度
        total_height = self.icon_size.height() + self.spacing + text_rect.height()
        return QtCore.QSize(self.max_text_width, total_height)

    def paint(self, painter, option, index):
        # 禁用文本省略,强制完整显示
        option.textElideMode = QtCore.Qt.ElideNone
        # 开启文本换行
        option.features |= QtWidgets.QStyleOptionViewItem.WrapText
        super().paint(painter, option, index)


class TreeViewDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(TreeViewDialog, self).__init__(parent)
        self.setMinimumSize(500, 400)
        self.create_widgets()
        self.create_layout()

    def create_widgets(self):
        # 替换为你自己的目录路径
        root_path = r"C:\Users\Documents\Test"

        self.model = QtWidgets.QFileSystemModel()
        self.model.setRootPath(root_path)

        self.list_view = QtWidgets.QListView()
        self.list_view.setViewMode(QtWidgets.QListView.IconMode)
        self.list_view.setResizeMode(QtWidgets.QListView.Adjust)
        self.list_view.setFlow(QtWidgets.QListView.LeftToRight)
        self.list_view.setMovement(QtWidgets.QListView.Snap)
        self.list_view.setModel(self.model)
        self.list_view.setRootIndex(self.model.index(root_path))
        # 设置图标尺寸,和委托里的icon_size保持一致
        self.list_view.setIconSize(QtCore.QSize(48, 48))
        self.list_view.setWordWrap(True)
        self.list_view.setTextElideMode(QtCore.Qt.ElideNone)
        # 给ListView设置自定义换行委托
        self.list_view.setItemDelegate(WrapTextDelegate(self.list_view, max_text_width=80))

    def create_layout(self):
        main_layout = QtWidgets.QHBoxLayout(self)
        main_layout.setContentsMargins(2, 2, 2, 2)
        main_layout.addWidget(self.list_view)


if __name__ == "__main__":
    app = QtWidgets.QApplication.instance()
    if not app:
        app = QtWidgets.QApplication(sys.argv)
    tree_view_dialog = TreeViewDialog()
    tree_view_dialog.show()
    sys.exit(app.exec_())

如果需要调整每个项的宽度,只要修改委托初始化时的max_text_width参数即可,委托会自动根据宽度计算文本换行后的高度,确保所有文本完整显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:57:00