当前位置: 首页 > article >正文

QListView、QListWidget、QTableView和QTableWidget

一、概念

        在Qt框架中,QListView、QListWidget、QTableView和QTableWidget都是用于显示列表或表格数据的控件。
QListView是一个基于模型-视图架构的控件,用于展示列表形式的数据。它本身并不存储数据,而是依赖于一个QAbstractListModel或其子类(如QStandardItemModel)来提供数据。
QListWidget是一个更为直接、易于使用的列表控件,它内部已经集成了一个简单的模型,可以直接添加、删除和修改项。
QTableView是一个基于模型-视图架构的表格控件,用于展示表格形式的数据。同样需要关联一个QAbstractTableModel或其子类(如QStandardItemModel)来提供数据。
QTableWidget是一个集成模型的表格控件,可以直接添加、删除和修改单元格数据。

二、架构与数据模型

控件架构类型数据模型继承关系
QListView视图类需外部模型(如 QStandardItemModel)‌继承自 QAbstractItemView
QListWidgetWidget类内置 QListWidgetItem 模型 ‌继承自 QListView
QTableView视图类需外部模型(如 QStandardItemModel、QSqlTableModel等)‌继承自 QAbstractItemView
QTableWidgetWidget类内置 QTableWidgetItem 模型 ‌继承自 QTableView

核心差异‌:

  • 视图类‌(QListView/QTableView)与模型分离,需手动绑定模型,灵活性高,适合动态数据处理‌。
  • Widget类‌(QListWidget/QTableWidget)内置模型,直接操作项(Item),开发效率高,但扩展性受限‌。

三、功能与适用场景

控件优势场景局限性
QListView动态数据绑定、多视图共享模型、自定义委托(Delegate)‌需编写模型逻辑,开发复杂度较高‌
QListWidget快速实现静态列表、少量数据展示(如配置项)‌数据量大时性能下降,难以扩展‌
QTableView多列数据展示、复杂表格逻辑(如数据库交互)‌需自定义模型,代码量较大‌
QTableWidget快速创建简单表格(如数据录入界面)‌无法复用模型,数据量大时性能低‌

四、优势

视图类优势‌:

  • 支持数据复用,适合动态更新和大数据量(如千级条目)‌。
  • 可通过委托(Delegate)自定义项渲染和交互逻辑‌。
    ‌示例‌:
    // QTableView 绑定数据库模型
    QSqlTableModel *model = new QSqlTableModel;
    model->setTable("employees");
    QTableView *view = new QTableView;
    view->setModel(model);

利用QItemDelegate,开发者可以为特定的列或者行定制绘制的样式,还可以定义编辑控件和编辑行为。它可以被用于处理复杂的编辑任务,比如自定义的下拉选择器或者复杂的输入验证。
Qt 提供了另外的基于组件的子类:QItemDelegate和 QStyledItemDelegate。默认的委托是 QStyledItemDelegate。二者的区别在于绘制和向视图提供编辑器的方式。QStyledItemDelegate使用当前样式绘制,并且能够使用 Qt Style Sheet,因此我们推荐在自定义委托时,使用 QStyledItemDelegate作为基类。
1)一个典型的使用QItemDelegate的场景是自定义表格视图中单元格的绘制和编辑方式。以下是一个简单的示例,展示了如何使用QItemDelegate来绘制一个带有特殊背景的单元格: 

#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QItemDelegate>class CustomDelegate : public QItemDelegate {
public:CustomDelegate(QObject *parent = nullptr) : QItemDelegate(parent) {}void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {// 调用基类的paint方法绘制默认样式QItemDelegate::paint(painter, option, index);// 自定义绘制逻辑painter->setBrush(QColor("orange")); // 设置背景色painter->drawRect(option.rect); // 绘制矩形填充背景}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QTableView tableView;QStandardItemModel model(5, 3); // 创建5行3列的数据模型CustomDelegate delegate; // 创建委托对象tableView.setModel(&model);tableView.setItemDelegate(&delegate); // 设置自定义委托for (int row = 0; row < 5; ++row) {for (int column = 0; column < 3; ++column) {QModelIndex index = model.index(row, column, QModelIndex());model.setData(index, QString("Item %1").arg(row * 3 + column), Qt::DisplayRole);}}tableView.show();return app.exec();
}

2)要创建一个有效的自定义 QItemDelegate 类,需要考虑以下几点:
继承 :从QStyledItemDelegate 继承,这取决于是否需要使用到Qt的样式系统。
构造函数 :定义构造函数以接受可能的参数,例如颜色或字体。
重写方法 :重写 createEditor 、 setEditorData 、 setModelData 、 updateEditorGeometry 、 paint 和 sizeHint 方法以提供自定义行为。
事件处理 :处理事件(如 鼠标事件 和 键盘事件 ),以实现特定的交互。
下面是一个自定义委托的示例,它提供了一个自定义的编辑器,用于编辑整数值: 

class IntegerDelegate : public QStyledItemDelegate {
public:IntegerDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}// 重写createEditor创建整数编辑器QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override {return new QSpinBox(parent);}// 将模型数据设置到编辑器中void setEditorData(QWidget *editor, const QModelIndex &index) const override {QSpinBox *spinBox = qobject_cast<QSpinBox *>(editor);if (!spinBox) return;spinBox->setValue(index.model()->data(index, Qt::EditRole).toInt());}// 将编辑器数据写回模型void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override {QSpinBox *spinBox = qobject_cast<QSpinBox *>(editor);if (!spinBox) return;model->setData(index, spinBox->value(), Qt::EditRole);}
};
#include <QStyledItemDelegate>
#include <QSpinBox>
#include <QComboBox>
#include <QPainter>class CustomDelegate : public QStyledItemDelegate {
public:explicit CustomDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}// 1. 创建编辑器控件QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override {if (index.column() == 0) { // 第一列使用数字输入框QSpinBox* editor = new QSpinBox(parent);editor->setRange(0, 100);return editor;} else if (index.column() == 1) { // 第二列使用下拉框QComboBox* editor = new QComboBox(parent);editor->addItems({"Option A", "Option B", "Option C"});return editor;}return QStyledItemDelegate::createEditor(parent, option, index);}// 2. 将模型数据加载到编辑器void setEditorData(QWidget* editor, const QModelIndex& index) const override {if (index.column() == 0) {int value = index.data(Qt::EditRole).toInt();QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor);spinBox->setValue(value);} else if (index.column() == 1) {QString text = index.data(Qt::EditRole).toString();QComboBox* comboBox = qobject_cast<QComboBox*>(editor);comboBox->setCurrentText(text);} else {QStyledItemDelegate::setEditorData(editor, index);}}// 3. 将编辑器数据写回模型void setModelData(QWidget* editor, QAbstractItemModel* model,const QModelIndex& index) const override {if (index.column() == 0) {QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor);model->setData(index, spinBox->value(), Qt::EditRole);} else if (index.column() == 1) {QComboBox* comboBox = qobject_cast<QComboBox*>(editor);model->setData(index, comboBox->currentText(), Qt::EditRole);} else {QStyledItemDelegate::setModelData(editor, model, index);}}// 4. 调整编辑器位置和尺寸void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option,const QModelIndex& index) const override {editor->setGeometry(option.rect.adjusted(2, 2, -2, -2)); // 边缘留2像素空隙}// 5. 自定义绘制逻辑void paint(QPainter* painter, const QStyleOptionViewItem& option,const QModelIndex& index) const override {if (index.column() == 2) { // 第三列绘制进度条int progress = index.data(Qt::UserRole).toInt();QStyleOptionProgressBar progressBarOption;progressBarOption.rect = option.rect.adjusted(5, 5, -5, -5);progressBarOption.minimum = 0;progressBarOption.maximum = 100;progressBarOption.progress = progress;progressBarOption.text = QString::number(progress) + "%";progressBarOption.textVisible = true;QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);} else {QStyledItemDelegate::paint(painter, option, index);}}// 6. 控制项尺寸QSize sizeHint(const QStyleOptionViewItem& option,const QModelIndex& index) const override {if (index.column() == 2) { // 进度列需要更大高度return QSize(200, 30); }return QStyledItemDelegate::sizeHint(option, index);}
};

Widget类优势‌:

  • 简化操作(如 addItem()setItem()),适合快速开发‌。
  • 支持直接嵌入自定义控件(如 setItemWidget())‌。
    ‌示例‌:
    // QListWidget 添加带图标的项
    QListWidgetItem *item = new QListWidgetItem("Text");
    item->setIcon(QIcon("icon.png"));
    listWidget->addItem(item);

相关文章:

QListView、QListWidget、QTableView和QTableWidget

一、概念 在Qt框架中&#xff0c;QListView、QListWidget、QTableView和QTableWidget都是用于显示列表或表格数据的控件。 QListView是一个基于模型-视图架构的控件&#xff0c;用于展示列表形式的数据。它本身并不存储数据&#xff0c;而是依赖于一个QAbstractListModel或其子…...

[贪心算法]-最大数(lambda 表达式的补充)

1.解析 我们一般使用的排序比较大小都是 a>b 那么a在b的前面 ab 无所谓 a<b a在b的后面 本题的排序则是 ab>ba 那么a在b的前面 abba 无所谓 ab<ba a在b的后面 2.代码 class Solution { public:string largestNumber(vector<int>& nums) {//1.先把所有…...

C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷二)

目录 1. 数组名与地址 2. 指针访问数组 3.一维数组传参本质 4.二级指针 5. 指针数组 6. 指针数组模拟二维数组 1. 数组名与地址 我们先看下面这个代码&#xff1a; int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int* p &arr[0]; 这里我们使用 &arr[0] 的方式拿到了数…...

python实现简单的图片去水印工具

python实现简单的图片去水印工具 使用说明&#xff1a; 点击"打开图片"选择需要处理的图片 在图片上拖拽鼠标选择水印区域&#xff08;红色矩形框&#xff09; 点击"去除水印"执行处理 点击"保存结果"保存处理后的图片 运行效果 先简要说明…...

使用dify+deepseek部署本地知识库

使用difydeepseek部署本地知识库 一、概述二、安装windows docker desktop1、确认系统的Hyper-v功能正常启用2、docker官网下载安装windows客户端3、安装完成后的界面如下所示 三、下载安装ollama四、部署本地deepseek五、本地下载部署dify5.1 下载dify的安装包5.2 将dify解压到…...

(C语言)指针与指针数组的使用教学(C语言基础教学)(指针教学)

指针是什么&#xff1f;指针怎么用&#xff1f;指针数组又是什么&#xff1f;&#xff1f;&#xff1f; 想必大家刚学C语言的时候对指针可谓是十分头疼了&#xff0c;听也听不懂&#xff0c;用也不会用 下面我来用我的理解来教你指针怎么用&#xff0c;还你一个脑子 1.指针的…...

【算法day13】最长公共前缀

最长公共前缀 https://leetcode.cn/problems/longest-common-prefix/submissions/612055945/ 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 class Solution { public:string longestCommonPrefix(vector<string&g…...

Effective C++ 剖析(条款1~9)

目录 条款01 视C为一个语言联邦(C由几部分组成) 条款02 尽量以 const,enum,inline 替换 #define 条款03 尽量使用 const 条款04 确定对象再使用前已经被初始化 条款05 了解c默默编写并调用那些函数 条款06 若不想使用编译器自动生成的函数就该明确拒绝 条款07 为多态基类…...

【Maven-plugin】有多少官方插件?

之前疏理了容器底层原理&#xff0c;现在回归主题,在阅读 next-public时发现 parent 将从多基础插件集成到 parent 仓库中单独维护&#xff0c;数量众多&#xff0c;故在此将所有插件分类整理。以达观其全貌&#xff0c;心中有数。 以下是 Apache Maven 官方维护的核心插件列表…...

Java高频面试之集合-13

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;为什么 hash 函数能降哈希碰撞&#xff1f; 哈希函数通过以下核心机制有效降低碰撞概率&#xff0c;确保不同输入尽可能映…...

RGV调度算法(三)--遗传算法

1、基于时间窗 https://wenku.baidu.com/view/470e9fd8b4360b4c2e3f5727a5e9856a57122693.html?_wkts_1741880736197&bdQuery%E7%8E%AF%E7%A9%BF%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95 2.2019年MathorCup高校数学建模挑战赛B题 2019-mathorcupB题-环形穿梭机调度模型&a…...

【数学建模】一致矩阵的应用及其在层次分析法(AHP)中的性质

一致矩阵在层次分析法(AHP)中的应用与性质 在层次分析法(AHP)中&#xff0c;一致矩阵是判断矩阵的一种理想状态&#xff0c;它反映了决策者判断的完全合理性和一致性&#xff0c;也就是为了避免决策者认为“A比B重要&#xff0c;B比C重要&#xff0c;但是C又比A重要”的矛盾。…...

YOLOv8轻量化改进——Coordinate Attention注意力机制

现在针对YOLOv8的架构改进越来越多&#xff0c;今天尝试引入了Coordinate Attention注意力机制以改进对小目标物体的检测效率。 yolov8的下载和安装参考我这篇博客&#xff1a; 基于SeaShips数据集的yolov8训练教程_seaships处理成yolov8-CSDN博客 首先我们可以去官网找到CA注…...

php开发转go的学习计划及课程资料信息

以下是为该课程体系整理的配套教材和教程资源清单,包含书籍、视频、官方文档和实战项目资源,帮助你系统化学习: Go语言学习教材推荐(PHP开发者适配版) 一、核心教材(按学习阶段分类) 1. 基础语法阶段(阶段一) 资源类型名称推荐理由链接/获取方式官方教程Go语言之旅交…...

解释 TypeScript 中的枚举(enum),如何使用枚举定义一组常量?

枚举&#xff08;Enum&#xff09;​ 是 TypeScript 中用于定义一组具名常量的核心类型&#xff0c;通过语义化的命名提升代码可读性&#xff0c;同时利用类型检查减少低级错误。 以下从定义方式、使用建议、注意事项三方面深入解析。 一、枚举的定义方式 1. 数字枚举 特性&…...

基于SpringBoot+Vue的驾校预约管理系统+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户、教练功能模块&#xff1a;用户管理、管理员管理、教练管理、教练预约管理、车辆管理、车辆预约管理、论坛管理、基础数据管理等技术选型&#xff1a;SpringBoot&#xff0c;Vue等测试环境&#xff1a;idea2024&#xff0c;j…...

ONNX:统一深度学习工作流的关键枢纽

引言 在深度学习领域&#xff0c;模型创建与部署的割裂曾是核心挑战。不同框架训练的模型难以在多样环境部署&#xff0c;而 ONNX&#xff08;Open Neural Network Exchange&#xff09;作为开放式神经网络交换格式&#xff0c;搭建起从模型创建到部署的统一桥梁&#xff0c;完…...

蓝桥杯————23年省赛 ——————平方差

3.平方差 - 蓝桥云课 一开始看题我还没有意识到问题的严重性 我丢&#xff0c;我想 的是用两层循环来做&#xff0c;后来我试了一下最坏情况&#xff0c;也就是l1 r 1000000000 结果运行半天没运行出来&#xff0c;我就知道坏了&#xff0c;孩子们&#xff0c;要出事&#…...

一、串行通信基础知识

一、串行通信基础知识 1.处理器与外部设备通信有两种方式 并行通信&#xff1a;数据的各个位用多条数据线同时传输。&#xff08;传输速度快&#xff0c;但占用引脚资源多。&#xff09; 串行通信&#xff1a;将数据分成一位一位的形式在一条数据线上逐个传输。&#xff08;线路…...

自带多个接口,完全免费使用!

做自媒体的小伙伴们&#xff0c;是不是经常为语音转文字的事儿头疼&#xff1f; 今天给大家推荐一款超实用的语音转文字软件——AsrTools&#xff0c;它绝对是你的得力助手&#xff01; AsrTools 免费的语音转文字软件 这款软件特别贴心&#xff0c;完全免费&#xff0c;而且操…...

大数据学习(70)-大数据调度工具对比

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…...

Qt QML解决SVG图片显示模糊的问题

前言 在QML中直接使用SVG图片&#xff0c;使用Image控件加载资源&#xff0c;显示出来图片是模糊的&#xff0c;很影响使用体验。本文介绍重新绘制SVG图片&#xff0c;然后注册到QML中使用。 效果图&#xff1a; 左边是直接使用Image加载资源显示的效果 右边是重绘后的效果 …...

【Linux我做主】基础命令完全指南上篇

Linux基础命令完全指南【上篇】 Linux基础命令完全指南github地址前言命令行操作的引入Linux文件系统树形结构的根文件系统绝对路径和相对路径适用场景Linux目录下的隐藏文件 基本指令目录和文件相关1. ls2. cd和pwdcdpwd 3. touch4. mkdir5. cp6. mv移动目录时覆盖写入的两种特…...

Designing Dashboards with SAP Analytics Cloud

Designing Dashboards with SAP Analytics Cloud...

项目实战系列:基于瑞萨RA6M5构建多节点OTA升级-系统设计<一>

项目背景 原嵌入式控制系统采用分布式模块化架构&#xff0c;由12个功能板卡&#xff08;通信控制、信号采集、驱动执行等&#xff09;组成。系统维护阶段存在以下痛点&#xff1a; 低效的本地烧录机制&#xff1a;各板卡固件升级需通过JTAG接口逐一手动连接JLINK仿真器&#x…...

hadoop集群配置-scp拓展使用

进行文件的拷贝&#xff1a;...

《AI大模型趣味实战》 No3:快速搭建一个漂亮的AI家庭网站-相册/时间线/日历/多用户/个性化配色/博客/聊天室/AI管家(下)

《AI大模型趣味实战》 No3&#xff1a;快速搭建一个漂亮的AI家庭网站-相册/时间线/日历/多用户/个性化配色/博客/聊天室/AI管家(下) 摘要 本文介绍了家庭网站V1.3版本的更新内容&#xff0c;主要聚焦于AI管家功能的优化与完善。V1.3版本对AI管家模块进行了全面升级&#xff0…...

华为OD机试 - 创建二叉树(Java 2024 E卷 200分)

题目描述 给定一系列树状结构操作的问题&#xff0c;通过 Q 次查询还原树结构并输出结果。题目要求实现一个类 Solution&#xff0c;其方法 recoverTree 需要根据输入的操作数组 operations 还原树的结构&#xff0c;并返回树的根节点。每个操作 operations[i] [height, inde…...

c++基础知识-图论进阶

一、拓扑排序 1、基础知识 1&#xff09;什么是拓扑排序 对一个有向无环图G进行拓扑排序&#xff0c;是将G中所有顶点排成一个线性序列&#xff0c;使得图中任意一对顶点u和v&#xff0c;若&#xff0c;则u在线性序列中出现在v之前。 2&#xff09;拓扑排序的操作方法 重复执行…...

[Java实战]Spring Boot服务CPU 100%问题排查:从定位到解决

Spring Boot服务CPU 100%问题排查&#xff1a;从定位到解决 1. 引言 当Spring Boot服务出现CPU占用率100%时&#xff0c;系统性能会急剧下降&#xff0c;甚至导致服务不可用。本文将通过真实代码案例&#xff0c;详细讲解如何快速定位问题根源&#xff0c;并提供解决方案。无…...