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

PyQt QListView IconMode:固定选中高亮尺寸与多行文本设置

解决QListView IconMode下短文本项高亮尺寸不一致与文本行数不足问题

针对QListView在IconMode模式下,短文本项选中高亮区域随文本长度缩小、文本行数过少的问题,可通过自定义QStyledItemDelegate实现以下两个需求:

  • 所有项的选中高亮区域保持统一尺寸
  • 文本标签至少显示一行高度

解决方案代码

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class MyItemDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, list_view, parent=None):
        super().__init__(parent)
        self.list_view = list_view

    def paint(self, painter, option, index):
        # 强制使用gridSize作为高亮背景的尺寸
        if option.state & QtWidgets.QStyle.State_Selected:
            grid_size = self.list_view.gridSize()
            # 计算居中的高亮矩形
            rect = QtCore.QRect(option.rect.center() - grid_size.center(), grid_size)
            painter.save()
            painter.setBrush(option.palette.highlight())
            painter.setPen(QtCore.Qt.NoPen)
            painter.drawRect(rect)
            # 恢复绘制状态,确保文本和图标正常绘制
            painter.restore()
            # 调整option的rect为gridSize对应的区域,保证内容居中
            option.rect = rect

        # 绘制文本时强制设置对齐方式,确保至少一行高度
        option.displayAlignment = QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter
        option.textElideMode = QtCore.Qt.ElideRight
        option.wordWrap = True
        super().paint(painter, option, index)

    def sizeHint(self, option, index):
        # 强制所有项的尺寸与gridSize一致
        return self.list_view.gridSize()

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

    def create_widgets(self):
        root_path = r"C:\Users\PCUser\Documents\pythonFiles"
        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))
        self.list_view.setGridSize(QtCore.QSize(80, 100))
        self.list_view.setUniformItemSizes(True)
        self.list_view.setWordWrap(True)
        self.list_view.setTextElideMode(QtCore.Qt.ElideRight)
        # 设置自定义委托
        self.list_view.setItemDelegate(MyItemDelegate(self.list_view))

    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() or QtWidgets.QApplication(sys.argv)
    dialog = TreeViewDialog()
    dialog.show()
    sys.exit(app.exec_())

关键逻辑说明

  1. 自定义Delegate实现统一高亮

    • 在paint方法中,检测到项处于选中状态时,使用list_view的gridSize作为高亮背景的绘制区域,确保所有项的高亮尺寸一致
    • 调整绘制选项的rect为gridSize对应的居中矩形,保证图标和文本在统一区域内居中显示
  2. 确保文本至少一行高度

    • 设置文本对齐方式为垂直+水平居中,开启自动换行
    • sizeHint方法直接返回gridSize,强制所有项的固定尺寸,文本区域高度由gridSize的高度决定,确保即使文本很短也会占据至少一行的显示空间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:25:19