Qt第十四章 模型视图

news2024/11/24 14:09:23

Model/View(模型/视图)结构

文章目录

  • Model/View(模型/视图)结构
    • 简介
    • 视图组件
    • Model/View结构的一些概念
    • 项目控件组(item Widgets)
    • 模型/视图 如何使用
    • 项目视图组
      • 设置行的颜色交替变换
      • 拖拽
      • 设置编辑操作
      • 其他操作
    • 选择模型
      • 自定义选择多行
      • 全选
    • 代理 Delegate
      • 现有代理
      • 自定义代理
        • 通过QWidget设置代理
        • 通过QPainter设置代理

简介

模型视图结构是Qt中用界面组件显示与编辑数据的一种结构,视图是显示和编辑数据的界面组件,模型是视图与原始数据之间的接口
在这里插入图片描述

视图组件

  • QListView 用于显示单列的列表数据,使用于一维数据的操作
void Widget::initListModel()
{
    listMod = new QStandardItemModel; // 创建模型
    ui->listView->setModel(listMod); // 视图设置模型
    // 增加
    listMod->appendRow(new QStandardItem("item1")); // 往模型里插入数据
    for (int i = 2; i < 10; i++)
        listMod->appendRow(new QStandardItem(QString("item%1").arg(i)));
    listMod->insertRow(2, new QStandardItem("insert item")); // 在第二行插入新的数据
    // 删除
    listMod->removeRows(2, 1); // 从第二行开始删除1个,不包括第二行
    listMod->removeRow(8); // 删除第九行
    listMod->takeRow(0); // 移除第一行,内存还在,没被释放
    // 查找
    QList<QStandardItem*> findItem = listMod->findItems("item5"); // 查找叫做item5的行,返回所有找到的行list
    if (findItem.isEmpty())
        qDebug() << "没找到";
    else
        for (auto& find : findItem)
            qDebug() << find->text();
    QStandardItem* findItem2 = listMod->item(3, 0); // 查找第三行,第0列的元素
    if (findItem2)
        qDebug() << findItem2->text();
    findItem2->setEditable(false); // 设置不可编辑,双击没反应
    findItem2->setEnabled(false); // 设置不启用,变成灰色
    
    findItem2->setData(QString("display item"), Qt::DisplayRole);
    // 在第五行插入一个元素
    QMap<int, QVariant> map;
    map.insert(Qt::DisplayRole, QString("display"));
    map.insert(Qt::DecorationRole, QColor(0, 0, 255));
    map.insert(Qt::ToolTipRole, QString("tool tip"));
    auto it = listMod->item(5);
    qDebug() << map;
    listMod->setItemData(it->index(), map);
    // 自定义数据或角色
    findItem2->setData(QString("这是自定义角色"), Qt::UserRole + 1);
    qDebug() << findItem2->data(Qt::UserRole + 1);
    // 清除角色
    findItem2->clearData();
}
  • QTreeView 用于显示树状结构的数据
void Widget::initTreeModel()
{
    treeMod = new QStandardItemModel;
    ui->treeView->setModel(treeMod);
    treeMod->appendRow(new QStandardItem("item1"));
    treeMod->insertRow(1); // 在第一行插入一个空白行

    QStandardItem* root1 = new QStandardItem("root1");
    QStandardItem* root2 = new QStandardItem("root2");
    root1->appendRow(new QStandardItem("sub item"));

    QList<QStandardItem*> subItem1s;
    for (int i = 0; i < 5; i++)
        subItem1s.append(new QStandardItem(QString("su1b%1").arg(i)));
    QList<QStandardItem*> subItem2s;
    for (int i = 0; i < 5; i++)
        subItem2s.append(new QStandardItem(QString("su2b%1").arg(i)));
    root1->appendRow(subItem1s); // 只添加了su1b0
    root2->appendRows(subItem2s); // 添加多行
    treeMod->appendRow(root1);
    treeMod->appendRow(root2);
}
  • QTableView 显示表格状数据
void Widget::initTableModel()
{
    tableMod = new QStandardItemModel;
    ui->tableView->setModel(tableMod);
    QList<QStandardItem*> items, items1;
    for (int i = 0; i < 10; i++) {
        items.append(new QStandardItem(QString("item%1").arg(i)));
        items1.append(new QStandardItem(QString("abc%1").arg(i)));
    }
    tableMod->appendColumn(items1);
    tableMod->appendRow(items);

    tableMod->setHorizontalHeaderLabels(QStringList() << "h1"
                                                      << "h2"
                                                      << "h3"); // 添加水平方向表头
}
  • QColumnView 用多个QListView显示树状层次结构
  • QHeaderView 提供行表头或列表头的视图组件,如QTableView的行表头列表头

Model/View结构的一些概念

在这里插入图片描述

项目控件组(item Widgets)

模型/视图 如何使用

项目视图组

设置行的颜色交替变换

    QPalette palet;
    palet.setBrush(QPalette::Base, Qt::yellow);
    palet.setBrush(QPalette::AlternateBase, Qt::green);
    ui->listView->setPalette(palet);
    ui->listView->setAlternatingRowColors(true); // 开启颜色交替

拖拽

    ui->tableView->setDragEnabled(true); // 设置可以拖
    ui->tableView->setDragDropMode(QAbstractItemView::DragDrop); // 支持拖和放

移动内容需要重写事件

设置编辑操作

 ui->listView->setEditTriggers(QListView::AnyKeyPressed); // 设置按下任意键编辑

其他操作

	ui->tableView->setSelectionBehavior(QTableView::SelectRows); // 设置选择方式,默认选择一行
	ui->tableView->setSortingEnabled(true); // 设置自动排序,默认升序

    ui->listView->setViewMode(QListView::IconMode); // 设置视图模式为图标视图
    ui->listView->setFlow(QListView::TopToBottom); // 设置排列丛上到下
    ui->listView->setResizeMode(QListView::Adjust); // 设置随窗口改变适应布局

    ui->tableView->hideColumn(8); // 把第八列隐藏
    ui->tableView->showColumn(8); // 显示

	ui->tableView->setCornerButtonEnabled(false); // 设置左上角是否允许双击全选,默认是允许的

选择模型

Widget::Widget(QWidget* parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , model(new QStandardItemModel)
{
    ui->setupUi(this);
    ui->tableView->setModel(model);

    QList<QStandardItem*> items[5];
    for (int i = 0; i < 5; i++)
        for (int j = 0; j < 10; j++)
            items[i].append(new QStandardItem(QString("item%1").arg(j)));
    for (int i = 0; i < 5; i++)
        model->appendColumn(items[i]);

    // 设置自定义选择区域
    QItemSelectionModel* selectModel = ui->tableView->selectionModel(); // 获取当前的选择模型
    QModelIndex leftTop = model->index(0, 0);
    QModelIndex rightBottom = model->index(4, 2);
    QItemSelection selection(leftTop, rightBottom);
    selectModel->select(selection, QItemSelectionModel::Select);

    // 获取当前选择区域,并且修改它
    QModelIndexList indexs = selectModel->selectedIndexes();
    for (auto& i : indexs) {
        qDebug() << i.data();
        QStandardItemModel* item = (QStandardItemModel*)i.model();
        item->setData(i, "123", Qt::DisplayRole);
        item->setData(i, QIcon("C:/Users/PVer/Pictures/Resource/派蒙.jpeg"), Qt::DecorationRole);
    }
}

在这里插入图片描述

自定义选择多行

 	QModelIndex idx1 = model->index(0, 0); // 第0行第0列
    QModelIndex idx2 = model->index(0, 1); // 第0行第1列
    QModelIndex idx3 = model->index(1, 0); // 第1行第0列
    QModelIndex idx4 = model->index(0, 2); // 第0行第2列
    QItemSelection sel(idx1, idx3);
    QItemSelection sel1(idx2, idx4);
    selectModel->select(sel, QItemSelectionModel::SelectionFlag(0x0002 | 0x0020)); // 选中0,2行
    selectModel->select(sel1, QItemSelectionModel::SelectionFlag(0x0002 | 0x0040)); // 选中1,2列

在这里插入图片描述

全选

    QModelIndex topLeft = model->index(0, 0); // 获取左上角
    QModelIndex bottomRight = model->index(model->rowCount() - 1, model->columnCount() - 1); // 获取右下角
    QItemSelection selAll(topLeft, bottomRight);
    selectModel->select(selAll, QItemSelectionModel::Select);

代理 Delegate

代理就是在视图组件上为编辑数据提供编辑器,如在表格组件中编辑一个单元格的数据时,缺省是使用一个QLineEdit编辑框。代理负责从数据模型获取相应的数据,然后显示在编辑器里,修改数据后,又将其保存到数据模型中。

现有代理

视图本身有一个代理,可以编辑

自定义代理

通过QWidget设置代理
  1. 给列表视图加入你创建的代理类
ui->tableView->setItemDelegate(new CustomDelegate); // 设置代理
  1. 创建一个代理的类CustomDelegate继承自QStyledItemDelegate
    头文件
#ifndef CUSTOMDELEGATE_H
#define CUSTOMDELEGATE_H

#include <QStyledItemDelegate>
#include <QWidget>

class CustomDelegate : public QStyledItemDelegate {
    Q_OBJECT
public:
    CustomDelegate(QObject* parent = nullptr);

    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
    void setEditorData(QWidget* editor, const QModelIndex& index) const override;
    void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
    void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};

#endif // CUSTOMDELEGATE_H

源文件

#include "CustomDelegate.h"
#include <QSpinBox>

CustomDelegate::CustomDelegate(QObject* parent)
    : QStyledItemDelegate(parent)
{
}

QWidget* CustomDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    QSpinBox* box = new QSpinBox(parent);
    box->setMaximum(100);
    box->setMinimum(0);
    box->setFrame(false); // 设置微调框不显示边框
    return box;
}

void CustomDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    int v = index.data().toInt();
    QSpinBox* box = dynamic_cast<QSpinBox*>(editor);
    box->setValue(v); // 设置微调框里的初始数值
}

void CustomDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    QSpinBox* box = dynamic_cast<QSpinBox*>(editor);
    box->interpretText();
    int v = box->value();
    model->setData(index, v, Qt::DisplayRole);
}

void CustomDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    editor->setGeometry(option.rect); // 设置微调框大小和位置和模型窗口重叠
}

  1. 此处是用微调框做的代理类,效果如图
    在这里插入图片描述
通过QPainter设置代理

QQ聊天的例子
在这里插入图片描述
新建头文件

#ifndef CUSTOMDELEGAT2_H
#define CUSTOMDELEGAT2_H

#include <QStyledItemDelegate>
#include <QWidget>

class CustomDelegat2 : public QStyledItemDelegate {
    Q_OBJECT
public:
    explicit CustomDelegat2(QObject* parent = nullptr);
    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
    void setEditorData(QWidget* editor, const QModelIndex& index) const override;
    virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
};

#endif // CUSTOMDELEGAT2_H

源文件

#include "CustomDelegat2.h"
#include <QPainter>

CustomDelegat2::CustomDelegat2(QObject* parent)
    : QStyledItemDelegate { parent }
{
}

void CustomDelegat2::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    QRect area = option.rect; // 获取绘制区域
    // 获取图标并绘制
    QRect r1 = QRect(area.topLeft(), QSize(area.width() / 3, area.height()));
    painter->drawPixmap(r1, QPixmap("C:/Users/PVer/Pictures/Resource/BinQQqq.bmp"));
    // 绘制名称
    QRect r2 = QRect(r1.topRight(), QSize(r1.width(), r1.height() / 2));
    painter->drawText(r2, "梦想盛开的地方");
    // 绘制消息
    QRect r3 = QRect(r2.bottomLeft(), r2.size());
    painter->drawText(r3, "是要做什么的");
    // 绘制日期
    QRect r4 = QRect(r2.topRight(), r2.size());
    painter->drawText(r4, "7-23");
}

QSize CustomDelegat2::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    return QSize(option.widget->width(), 50);
}

QWidget* CustomDelegat2::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    return new QWidget(parent);
}

void CustomDelegat2::setEditorData(QWidget* editor, const QModelIndex& index) const
{
}

void CustomDelegat2::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
}

代码里加入树视图,并且设置自定义模型

    listModel = new QStandardItemModel;
    ui->listView->setModel(listModel);
    ui->listView->setItemDelegate(new CustomDelegat2);
    listModel->appendRow(new QStandardItem);
    listModel->appendRow(new QStandardItem);
    listModel->appendRow(new QStandardItem);

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2039526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打靶记录10——hacksudo---Thor

靶机&#xff1a; https://download.vulnhub.com/hacksudo/hacksudo---Thor.zip难度&#xff1a; 中 目标&#xff1a; 取得root权限flag 涉及攻击方法&#xff1a; 主机发现端口扫描Web目录爬取开源源码泄露默认账号密码SQL注入破壳漏洞GTFOBins提权 主机发现&#xff…

Windows的cmd命令行使用Linux类命令

Windows的cmd使用Linux类命令 去我的个人博客观看&#xff0c;观感更佳哦&#xff0c;&#x1f619;&#x1f619; 前言 我在使用Vscode编写C/C代码的时候&#xff0c;经常会用到Shell(你可以理解为命令行)&#xff0c;但是我不得不说Windows下Dos命令极其难用且拉跨&#x1f…

【应用层协议】自定义协议 {定义结构化数据;数据格式转换:序列化和反序列化,使用json库进行数据格式交换;分包和解包:为报文内容添加报头}

一、简单了解TCP协议&#xff08;引子&#xff09; 1.1 三次握手 三次握手就是客户端向服务端发起连接的过程 服务器初始化 调用socket&#xff0c;创建套接字文件 调用bind&#xff0c;将当前的文件描述符和ip/port绑定在一起&#xff1b;如果这个端口已经被其他进程占用了&…

整理 酷炫 Flutter 开源UI框架 按钮

flutter_percent_indicator Flutter 百分比指示器库 项目地址&#xff1a;https://github.com/diegoveloper/flutter_percent_indicator 项目Demo&#xff1a;https://download.csdn.net/download/qq_36040764/89631340

springboot整合doris(doris创建表)

Doris 的数据模型主要分为 3 类: 明细模型(Duplicate Key Model):允许指定的 Key 列重复;适用于必须保留所有原始数据记录的情况主键模型(Unique Key Model):每一行的 Key 值唯一;可确保给定的 Key 列不会存在重复行聚合模型(Aggregate Key Model):可根据 Key 列聚…

力扣每日一题 特殊数组 II 前缀和

Problem: 3152. 特殊数组 II &#x1f468;‍&#x1f3eb; 参考题解 Code class Solution {public boolean[] isArraySpecial(int[] nums, int[][] queries) {int[] s new int[nums.length];for (int i 1; i < nums.length; i) {s[i] s[i - 1] (nums[i - 1] % 2 num…

用R语言进行数据的特征缩放主要方法

下面内容摘录自《R 语言与数据科学的终极指南》专栏文章的部分内容&#xff0c;每篇文章都在 5000 字以上&#xff0c;质量平均分高达 94 分&#xff0c;看全文请点击下面链接&#xff1a; 4章11节&#xff1a;用R做数据重塑&#xff0c;数据的特征缩放和特征可视化-CSDN博客文…

第八季完美童模全球冠军·韩嘉滢 破浪扬帆写就传奇

在这个充满奇迹与梦想的舞台上&#xff0c;星光少女韩嘉滢以她独有的光芒&#xff0c;照亮了第八季完美童模的每一个角落。从亚特兰蒂斯的神秘海域到典故里的中国古韵&#xff0c;她以多变的风格与卓越的表现&#xff0c;征服了全球观众的心&#xff0c;最终荣登全球冠军的宝座…

K8S资源之Service

概念 将一组 Pods 公开为网络服务的抽象方法。 ClientIP 模型 集群内访问类型。 命令行 # 暴露端口 kubectl expose deployment my-dep-nginx --port8000 --target-port80Yml文件 apiVersion: v1 kind: Service metadata:labels:app: my-dep-nginxname: my-dep-nginx spe…

中小型企业可用的数据采集监控平台 为生产带来众多改变

中小型企业采用数据采集监控平台可以显著提升生产效率、优化生产流程、增强决策能力&#xff0c;并带来一系列积极的改变。 数据采集监控平台可提供从边缘感知设备到云端的数据采集、存储、分析、可视化等服务&#xff0c;实现生产工艺流程仿真、设备运行状态监控、数据报表、趋…

渗透测试实战-菠菜站渗透测试(Nacos反序列化漏洞利用)

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

leetcode 103.二叉树的锯齿形层序遍历

1.题目要求: 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。2.做题思路:由题我们可以判断&#xff0c;树中每到偶数…

IV(电流-电压)测试和CV(电容-电压)测试

IV&#xff08;电流-电压&#xff09;测试和CV&#xff08;电容-电压&#xff09;测试是半导体参数表征中非常重要的两种测试方法。 一、IV测试&#xff08;电流-电压测试&#xff09; 1. 定义与目的 IV测试是测量半导体器件在不同电压下的电流响应&#xff0c;以评估其电学…

树莓派智能语音助手之ASR – SpeechRecognition+PocketSphinx

想要让树莓派成为智能语音助手&#xff0c;除了会“说”&#xff0c;也要会“听”。接下来&#xff0c;就要让它实现ASR&#xff08;语音识别&#xff09;功能了。 本来想用sherpa-onnx来实现离线语音识别的&#xff0c;可惜&#xff0c;我的树莓派系统太老了&#xff0c;折腾…

mybatis常见面试问题

0.原生JDBC样例: public class MainClass { public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 加载数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 建立连接 String url = &q…

视觉SLAM ch3补充——在Linux中配置VScode以及CMakeLists如何添加Eigen库

ch3中的所有代码&#xff0c;除了在kdevelop中运行&#xff0c;还可以在VScode中运行。下面将简要演示配置过程&#xff0c;代码不再做解答&#xff0c;详细内容在下面的文章中。&#xff08;这一节中的pangolin由于安装过程中会出现很多问题&#xff0c;且后续内容用不到该平台…

重磅官宣!追光少年【彭禹锦】荣担任中国美育促进网amp;IPA美育中国行代言人

在美育事业蓬勃发展的今天&#xff0c;一位年仅15岁的少年以其非凡的艺术才华和积极向上的精神风貌&#xff0c;成为了万众瞩目的焦点。中国美育促进网与IPA美育中国行正式宣布&#xff0c;才华横溢、正能量满满的追光少年彭禹锦受邀担任“中国美育促进网&IPA美育中国行”代…

c++中__int128的使用

需要10^30才可以存&#xff0c;我们可以用__int128来算 #include<bits/stdc.h>using namespace std;bool is_sqr(__int128 x) {__int128 l -1, r 1e16;while (r - l > 1) {__int128 m (l r) / 2;__int128 m2 m * m;if (m2 < x) {l m;} else {r m;}}if (l *…

【机器学习】RNN循环神经网络的基本概念、工作原理(含python代码)和应用领域

引言 递归神经网络&#xff08;RNN&#xff09;是一类用于处理序列数据的神经网络。它们在处理如时间序列数据、语音、文本和其他序列格式数据时特别有用 文章目录 引言一、RNN的基本概念1.1 RNN的定义组成1.1.1 单个神经元1.1.2 网络结构 1.2 RNN的工作原理及代码示例1.2.1 循…

8月7日-8日学习

首先是昨天看到的gemma 2 中训练2B模型用了知识蒸馏&#xff0c;找了一下技术报告 结果先找到了一代的半天没有看到知识蒸馏的部分 然后在二代里面找到了 只有很小的一部分 就是用小模型学习大模型的概率预测分布 然后这里的话又找到了华为发布的小模型论文 Rethinking Optim…