QListView图标模式搭配QFileSystemModel如何实现项目文本自动换行?
解决方法
问题原因
- 你开启了
setUniformItemSizes(True),该配置会强制所有列表项使用相同尺寸,忽略每个项的独立高度计算,导致换行后的文本高度无法被正确识别 - 固定设置了
GridSize高度为80,当图标+换行后文本的总高度超过80时,文本自然会被截断
实现步骤
- 自定义支持自动换行计算的
QStyledItemDelegate,重写尺寸计算和绘制逻辑 - 移除原有错误配置,为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
相关产品推荐
相关产品推荐

