ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

qlistview

qlistview

QListView 基础用法整理(基于你这份代码)

QListView 是视图View,本身不存数据;数据放在Model模型里面,View只负责展示。
两种常用模型:

  1. QStringListModel:只存简单字符串,不能设置图标、颜色、字体
  2. QStandardItemModelQStandardItem作为条目,可以设置文字、图标、字体、颜色、自定义附加数据
# # -*- coding: utf-8 -*-# '''# 【简介】# PyQt5中 QListView 例子# '''# from PyQt5.QtWidgets import QApplication, QWidget , QVBoxLayout , QListView, QMessageBox# from PyQt5.QtCore import QStringListModel# import sys# class ListViewDemo(QWidget):# def __init__(self, parent=None):# super(ListViewDemo, self).__init__(parent)# self.setWindowTitle("QListView 例子")# self.resize(300, 270)# layout = QVBoxLayout()# listView = QListView()# slm = QStringListModel();# self.qList = ['Item 1','Item 2','Item 3','Item 4' ]# slm.setStringList(self.qList)# listView.setModel(slm )# listView.clicked.connect(self.clicked)# layout.addWidget( listView )# self.setLayout(layout)# def clicked(self, qModelIndex):# QMessageBox.information(self, "QListView", "你选择了: "+ self.qList[qModelIndex.row()])# if __name__ == "__main__":# app = QApplication(sys.argv)# win = ListViewDemo()# win.show()# sys.exit(app.exec_())importsysfromPyQt5.QtWidgetsimport(QApplication,QWidget,QHBoxLayout,QVBoxLayout,QFrame,QListView,QPushButton,QAbstractItemView)fromPyQt5.QtCoreimportQStringListModel,QSize,QtfromPyQt5.QtGuiimportQStandardItemModel,QStandardItem,QBrush,QColor,QFont,QIcon,QPixmapclassMainWidget(QWidget):def__init__(self):super().__init__()self.setWindowTitle("QListView 两种Model + 缩略图预览")self.resize(1400,600)main_layout=QHBoxLayout(self)# ========= Frame1:QStringListModel 纯字符串列表 =========frame1=QFrame()frame1.setFrameShape(QFrame.Box)frame1.setLineWidth(1)lay1=QVBoxLayout(frame1)self.listView1=QListView()self.listView1.setSelectionMode(QAbstractItemView.SingleSelection)#同一时刻只能选中 1 行;点新条目,旧的自动取消选中。lay1.addWidget(self.listView1)btn_lay1=QVBoxLayout()self.btn1_add=QPushButton("添加字符串")self.btn1_del=QPushButton("删除选中")self.btn1_clear=QPushButton("清空全部")self.btn1_print=QPushButton("打印选中")btn_lay1.addWidget(self.btn1_add)btn_lay1.addWidget(self.btn1_del)btn_lay1.addWidget(self.btn1_clear)btn_lay1.addWidget(self.btn1_print)lay1.addLayout(btn_lay1)self.str_data=["苹果","香蕉","橙子"]self.str_model=QStringListModel()#字符串列表模型self.str_model.setStringList(self.str_data)#设置字符串列表self.listView1.setModel(self.str_model)#设置模型self.btn1_add.clicked.connect(self.str_add_item)self.btn1_del.clicked.connect(self.str_del_selected)self.btn1_clear.clicked.connect(self.str_clear)self.btn1_print.clicked.connect(self.str_print_sel)# ========= Frame2:QStandardItemModel‑QListView(单列表带颜色) =========frame2=QFrame()frame2.setFrameShape(QFrame.Box)frame2.setLineWidth(1)lay2=QVBoxLayout(frame2)self.listView2=QListView()self.listView2.setSelectionMode(QAbstractItemView.SingleSelection)#同一时刻只能选中 1 行;点新条目,旧的自动取消选中。lay2.addWidget(self.listView2)btn_lay2=QVBoxLayout()self.btn2_add=QPushButton("添加彩色Item")self.btn2_del=QPushButton("删除选中")self.btn2_clear=QPushButton("清空全部")self.btn2_print=QPushButton("打印选中")btn_lay2.addWidget(self.btn2_add)btn_lay2.addWidget(self.btn2_del)btn_lay2.addWidget(self.btn2_clear)btn_lay2.addWidget(self.btn2_print)lay2.addLayout(btn_lay2)self.item_model=QStandardItemModel()#标准项模型self.listView2.setModel(self.item_model)#设置模型self.init_standard_items()self.btn2_add.clicked.connect(self.item_add_item)self.btn2_del.clicked.connect(self.item_del_selected)self.btn2_clear.clicked.connect(self.item_clear)self.btn2_print.clicked.connect(self.item_print_sel)# ========= Frame3:新增 — QListView 缩略图网格模式 IconMode =========frame3=QFrame()frame3.setFrameShape(QFrame.Box)frame3.setLineWidth(1)lay3=QVBoxLayout(frame3)self.listView_thumb=QListView()lay3.addWidget(self.listView_thumb)btn_lay3=QVBoxLayout()self.btn3_add=QPushButton("添加缩略图项")self.btn3_del=QPushButton("删除选中")self.btn3_clear=QPushButton("清空")btn_lay3.addWidget(self.btn3_add)btn_lay3.addWidget(self.btn3_del)btn_lay3.addWidget(self.btn3_clear)lay3.addLayout(btn_lay3)# 缩略图用 QStandardItemModelself.thumb_model=QStandardItemModel()#标准项模型self.listView_thumb.setModel(self.thumb_model)#设置模型# 关键缩略图配置:网格图标模式self.listView_thumb.setViewMode(QListView.IconMode)#设置视图模式为图标模式self.listView_thumb.setIconSize(QSize(80,80))#设置图标大小self.listView_thumb.setSpacing(12)#设置图标间距self.listView_thumb.setResizeMode(QListView.Adjust)#设置调整模式为自动调整self.listView_thumb.setSelectionMode(QAbstractItemView.SingleSelection)#设置选择模式为单选# 初始化几条示例(这里用系统默认图标,你后续替换成自己图片路径 QIcon("xxx.jpg"))self.init_thumb_items()self.btn3_add.clicked.connect(self.thumb_add_item)self.btn3_del.clicked.connect(self.thumb_del_selected)self.btn3_clear.clicked.connect(self.thumb_clear)# 三个frame全部加到主水平布局main_layout.addWidget(frame1)main_layout.addWidget(frame2)main_layout.addWidget(frame3)# ------------------- Frame1 QStringListModel -------------------defstr_add_item(self):self.str_data.append(f"新项目_{len(self.str_data)+1}")self.str_model.setStringList(self.str_data)defstr_del_selected(self):idxs=self.listView1.selectedIndexes()ifnotidxs:returnrows=sorted([i.row()foriinidxs],reverse=True)forrinrows:delself.str_data[r]self.str_model.setStringList(self.str_data)defstr_clear(self):self.str_data.clear()self.str_model.setStringList(self.str_data)defstr_print_sel(self):idxs=self.listView1.selectedIndexes()foridxinidxs:text=self.str_model.data(idx,Qt.DisplayRole)print(f"【字符串列表】row={idx.row()}, text={text}")# ------------------- Frame2 QStandardItemModel 普通列表 -------------------definit_standard_items(self):font_bold=QFont()font_bold.setBold(True)item1=QStandardItem("普通条目")self.item_model.appendRow(item1)item2=QStandardItem("告警条目(红色粗体)")item2.setForeground(QBrush(QColor(255,0,0)))item2.setFont(font_bold)self.item_model.appendRow(item2)item3=QStandardItem("提示条目(蓝色)")item3.setForeground(QBrush(QColor(0,0,255)))self.item_model.appendRow(item3)defitem_add_item(self):importrandom colors=[(0,0,0),(255,0,0),(0,180,0),(0,0,255)]r,g,b=random.choice(colors)item=QStandardItem(f"动态添加_{self.item_model.rowCount()+1}")item.setForeground(QBrush(QColor(r,g,b)))self.item_model.appendRow(item)defitem_del_selected(self):idxs=self.listView2.selectedIndexes()ifnotidxs:returnrows=sorted([i.row()foriinidxs],reverse=True)forrinrows:self.item_model.removeRow(r)defitem_clear(self):self.item_model.clear()defitem_print_sel(self):idxs=self.listView2.selectedIndexes()foridxinidxs:item=self.item_model.itemFromIndex(idx)print(f"【复杂Item列表】row={idx.row()}, text={item.text()}")# ------------------- Frame3 缩略图列表 IconMode -------------------definit_thumb_items(self):"""初始化缩略图项,现在用内置文件图标;实际项目替换 QIcon("你的图片.jpg")"""foriinrange(300):item=QStandardItem(f"图片_{i+1}")# 这里演示,你改为:item.setIcon(QIcon("/home/xxx/1.jpg"))#item.setIcon(QIcon.fromTheme("image-x-generic"))item.setIcon(QIcon("images/python.jpg"))self.thumb_model.appendRow(item)defthumb_add_item(self):cnt=self.thumb_model.rowCount()+1item=QStandardItem(f"图片_{cnt}")item.setIcon(QIcon.fromTheme("image-x-generic"))self.thumb_model.appendRow(item)defthumb_del_selected(self):idxs=self.listView_thumb.selectedIndexes()ifnotidxs:returnrows=sorted([i.row()foriinidxs],reverse=True)forrinrows:self.thumb_model.removeRow(r)defthumb_clear(self):self.thumb_model.clear()if__name__=="__main__":app=QApplication(sys.argv)w=MainWidget()w.show()sys.exit(app.exec_())

一、核心概念

  1. View(视图)QListView,负责界面渲染、鼠标点击、选择;不保存业务数据
  2. Model(模型):保存真实数据,View通过setModel(model)绑定模型
  3. QModelIndex:索引对象,代表模型中某一行;点击、选中都会返回索引
  4. 选择模式setSelectionMode():控制单选/多选
  5. 视图模式:
    • 默认ListMode:垂直列表一条条显示
    • IconMode:网格缩略图图标模式

二、QListView + QStringListModel(纯字符串)

适用场景:只展示文本,不需要图标颜色。

#1 模型self.str_data=["苹果","香蕉","橙子"]# python列表维护数据源self.str_model=QStringListModel()self.str_model.setStringList(self.str_data)#2 视图self.listView1=QListView()self.listView1.setSelectionMode(QAbstractItemView.SingleSelection)#单选self.listView1.setModel(self.str_model)#绑定模型#3 信号:点击条目self.listView1.clicked.connect(self.xxx_slot)

常用操作

# 1.新增:修改python list,再整体setStringList刷新self.str_data.append("新项目")self.str_model.setStringList(self.str_data)# 2.删除选中:拿到选中索引 → 拿到row,从大到小删idxs=self.listView1.selectedIndexes()rows=sorted([i.row()foriinidxs],reverse=True)forrinrows:delself.str_data[r]self.str_model.setStringList(self.str_data)#3 清空self.str_data.clear()self.str_model.setStringList(self.str_data)#4 获取选中文本,必须带上Qt.DisplayRoleforidxinidxs:text=self.str_model.data(idx,Qt.DisplayRole)

⚠️注意:QStringListModel没有appendRow只能整体setStringList()更新
底层数据在自己维护的python list,模型只是镜像。

三、QListView + QStandardItemModel(支持图标/颜色/字体)

每个条目是QStandardItem,不用外部python list维护,数据存在model内部。

#1 模型self.item_model=QStandardItemModel()#2 视图self.listView2=QListView()self.listView2.setSelectionMode(QAbstractItemView.SingleSelection)self.listView2.setModel(self.item_model)#3 添加条目item=QStandardItem("告警条目")item.setForeground(QBrush(QColor(255,0,0)))#文字颜色item.setFont(font_bold)#字体item.setIcon(QIcon("xxx.jpg"))#图标self.item_model.appendRow(item)#新增一行#4 删除选中idxs=self.listView2.selectedIndexes()rows=sorted([i.row()foriinidxs],reverse=True)forrinrows:self.item_model.removeRow(r)#5 清空全部self.item_model.clear()#6 通过index拿到itemitem=self.item_model.itemFromIndex(index)text=item.text()

Item常用API

item.setText("xxx")#设置文字item.setForeground(QBrush(color))#文字颜色item.setFont(QFont)#字体粗体斜体item.setIcon(QIcon)#图标item.setData(value,Qt.UserRole)#保存自定义附加数据(路径、id等)

四、IconMode 网格缩略图模式(你代码Frame3)

self.listView_thumb.setViewMode(QListView.IconMode)#切换为网格图标模式self.listView_thumb.setIconSize(QSize(80,80))#图标显示大小self.listView_thumb.setSpacing(12)#item之间间距self.listView_thumb.setResizeMode(QListView.Adjust)#窗口大小改变自动重排图标self.listView_thumb.setSelectionMode(QAbstractItemView.SingleSelection)

重要提醒:
IconMode只是显示样式变网格,底层依然是QStandardItemModel一维行模型,没有变成真正表格。

五、选择模式 setSelectionMode 4种枚举

QAbstractItemView.SingleSelection#单选(代码用的),点新的取消旧的QAbstractItemView.MultiSelection#点击切换选中状态,可多选,不需要CtrlQAbstractItemView.ExtendedSelection#Ctrl/Shift多选,类似文件管理器QAbstractItemView.NoSelection#禁止选中,仅浏览

六、常用信号

#点击某一条目,会传回QModelIndexlistView.clicked.connect(self.slot_func)#选中发生变化listView.selectionModel().selectionChanged.connect(self.slot_func)

七、关键坑点总结

  1. QStringListModel.data(index)必须传第二个参数role,PyQt5没有C++默认参数。
    text=model.data(index,Qt.DisplayRole)
  2. 删除多条选中:row必须降序排序reverse=True,否则前面删除后行号偏移,删错。
  3. QStringListModel没有appendRowQStandardItemModelappendRow(item)
  4. IconMode只是外观网格,逻辑上还是一维行;想要真正多列表格,用QTableView
  5. 如果需要点击缩略图弹出原图预览:
    • item通过item.setData(原图路径,Qt.UserRole)保存原图路径
    • 点击回调用index.data(Qt.UserRole)取出路径加载大图,不要从缩略图标拿图,会模糊

八、两者模型对比简表

QStringListModelQStandardItemModel
数据单元字符串QStandardItem对象
图标/字体/颜色❌不支持✅支持
添加数据setStringList(整个list)appendRow(item)
删除行修改外部python list再刷新removeRow(row)
自定义附加数据❌不支持✅setData(…,Qt.UserRole)
适合场景简单纯文本列表图文、带颜色、缩略图列表
返回列表