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_())
关键逻辑说明
自定义Delegate实现统一高亮
- 在
paint方法中,检测到项处于选中状态时,使用list_view的gridSize作为高亮背景的绘制区域,确保所有项的高亮尺寸一致 - 调整绘制选项的
rect为gridSize对应的居中矩形,保证图标和文本在统一区域内居中显示
- 在
确保文本至少一行高度
- 设置文本对齐方式为垂直+水平居中,开启自动换行
sizeHint方法直接返回gridSize,强制所有项的固定尺寸,文本区域高度由gridSize的高度决定,确保即使文本很短也会占据至少一行的显示空间
内容的提问来源于stack exchange,提问作者user3696118
相关产品推荐
相关产品推荐

