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

QLisview 实现model deletage,并且在不需要编辑的情况下自定义UI

在QListView中自定义model、deletage,普遍是使用paint函数绘制;
如果要使用自己的自定义QWidget,比如利用ui文件和子当以类创建一个自定义的Item,如何再QListView中实现。

核心代码:
为新项启用持久编辑器 重中之重
ui->listView->openPersistentEditor(m_listModel->index(i));

以下用一个QListView的例子实现上述情景

自定义模型文件


#pragma execution_character_set("utf-8")
#ifndef MULTICHANNELTESTSYSTEM_MCSTRECIPELISTMODEL_H
#define MULTICHANNELTESTSYSTEM_MCSTRECIPELISTMODEL_H#include <QObject>
#include <QAbstractListModel>
#include <QAbstractItemModel>
class MCSTRecipeConfigDataStr;class MCSTRecipeListModel : public QAbstractListModel
{Q_OBJECTpublic:MCSTRecipeListModel(QObject *parent = nullptr);~MCSTRecipeListModel();
public:// 返回行数int rowCount(const QModelIndex& parent = QModelIndex()) const override;// 获取数据QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;// 设置数据bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;Qt::ItemFlags flags(const QModelIndex& index) const override;
public:// 添加数据项void insertData(QSharedPointer<MCSTRecipeConfigDataStr>);
private:QList<QSharedPointer<MCSTRecipeConfigDataStr>> m_recipeDataList;
};//cpp文件
#include "MCSTRecipeListModel.h"
#include "MCSTData.hpp"
MCSTRecipeListModel::MCSTRecipeListModel(QObject *parent): QAbstractListModel(parent)
{
}MCSTRecipeListModel::~MCSTRecipeListModel()
{
}// 返回行数
int MCSTRecipeListModel::rowCount(const QModelIndex& parent) const
{return m_recipeDataList.size();
}// 获取数据
QVariant MCSTRecipeListModel::data(const QModelIndex& index, int role) const 
{QVariant variantRet;int row = index.row();if (row >= m_recipeDataList.size() || (!index.isValid())){return QVariant();}auto item = m_recipeDataList.at(row);if (role == Qt::UserRole) {variantRet = QVariant::fromValue<const QSharedPointer<MCSTRecipeConfigDataStr>>(item);return variantRet;}        else if (role == Qt::UserRole + 1) {return QVariant();}        return QVariant();
}// 设置数据
bool MCSTRecipeListModel::setData(const QModelIndex& index, const QVariant& configData,int role) 
{bool ret = false;int row = index.row();qDebug() << "setData row:" << row <<" data size:"<< m_recipeDataList.size();if (row >= m_recipeDataList.size() || (!index.isValid())){qDebug() << "setData index avalid" ;return ret;}switch (role) {case Qt::UserRole: {auto data = configData.value<QSharedPointer<MCSTRecipeConfigDataStr>>();//m_recipeDataList[row] = data;m_recipeDataList[row]->m_recipeName = data->m_recipeName;m_recipeDataList[row]->m_recipeModifyTime = data->m_recipeModifyTime;m_recipeDataList[row]->m_recipeType = data->m_recipeType;m_recipeDataList[row]->m_recipePath = data->m_recipePath;ret = true;}break;case Qt::UserRole + 1: {}break;case Qt::UserRole + 2: {}break;default:break;}//发送信号触发刷新//emit dataChanged(index, index, QVector<int>() << role);emit dataChanged(index, index, { role }); // 通知数据变化return ret;
}Qt::ItemFlags MCSTRecipeListModel::flags(const QModelIndex& index) const
{return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
}void MCSTRecipeListModel::insertData(QSharedPointer<MCSTRecipeConfigDataStr> data) 
{int r = m_recipeDataList.size();qDebug() << "insertData r:" << r<<",rowCount"<< this->rowCount();beginInsertRows(QModelIndex(), this->rowCount(), this->rowCount());m_recipeDataList.push_back(data);endResetModel();  
}

自定义代理文件


#pragma execution_character_set("utf-8")
#ifndef MULTICHANNELTESTSYSTEM_MCSTRECIPELISTDELETAGE_H
#define MULTICHANNELTESTSYSTEM_MCSTRECIPELISTDELETAGE_H#include <QObject>
#include <QLineEdit>
#include <QWidget>
#include <QObject>
#include <QModelIndex>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QAbstractItemModel>class MCSTListItemWidget;class MCSTRecipeListDeletage : public QStyledItemDelegate
{Q_OBJECT
public:explicit MCSTRecipeListDeletage(QObject *parent = nullptr);~MCSTRecipeListDeletage();protected: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;QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;//处理鼠标事件bool editorEvent(QEvent* event,QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)override;
};//代理文件CPP#include "MCSTRecipeListDeletage.h"
#include "MCSTListItemWidget.h"
#include <MCSTData.hpp>MCSTRecipeListDeletage::MCSTRecipeListDeletage(QObject *parent): QStyledItemDelegate(parent)
{}MCSTRecipeListDeletage::~MCSTRecipeListDeletage()
{
}QWidget* MCSTRecipeListDeletage::createEditor(QWidget* parent,const QStyleOptionViewItem& option,const QModelIndex& index) const     
{// 从 Model 获取数据//auto data = index.data(Qt::UserRole).value<QSharedPointer<MCSTRecipeConfigDataStr>>();MCSTListItemWidget* widget = new MCSTListItemWidget(parent);//widget->setRecipeName(data->m_recipeName);//widget->setRecipeDate(data->m_recipeModifyTime);//widget->setRecipePath(data->m_recipePath);//widget->setRecipeType(data->m_recipeType);qDebug() << "createEditor";return widget;
}void MCSTRecipeListDeletage::setEditorData(QWidget* editor, const QModelIndex& index)const
{    MCSTListItemWidget* widget = qobject_cast<MCSTListItemWidget*>(editor);if (widget == nullptr)return;qDebug() << "setEditorData";// 从模型中获取结构体数据QSharedPointer<MCSTRecipeConfigDataStr> data = index.model()->data(index, Qt::UserRole).value<QSharedPointer<MCSTRecipeConfigDataStr>>();qDebug() << "setEditorData name:"<< data->m_recipeName;qDebug() << "setEditorData modifyTime:" << data->m_recipeModifyTime;qDebug() << "setEditorData recipeType:" << data->m_recipeType;qDebug() << "setEditorData recipePath:" << data->m_recipePath;widget->setRecipeName(data->m_recipeName);widget->setRecipeDate(data->m_recipeModifyTime);widget->setRecipeType(data->m_recipeType);widget->setRecipePath(data->m_recipePath);
}void MCSTRecipeListDeletage::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const 
{MCSTListItemWidget* widget = qobject_cast<MCSTListItemWidget*>(editor); if (widget == nullptr)return;qDebug() << "setModelData";//从编辑器中获取数据信息QSharedPointer<MCSTRecipeConfigDataStr> data(new MCSTRecipeConfigDataStr);data->m_recipeName          = widget->getRecipeName() ;data->m_recipeModifyTime    = widget->getRecipeDate() ;data->m_recipeType          = widget->getRecipeType() ;data->m_recipePath          = widget->getRecipePath() ;// 设置模型中的数据model->setData(index,QVariant::fromValue<QSharedPointer<MCSTRecipeConfigDataStr>>(data),Qt::UserRole);
}void MCSTRecipeListDeletage::updateEditorGeometry(QWidget* editor,const QStyleOptionViewItem& option,const QModelIndex& index)const 
{editor->setGeometry(option.rect);
}QSize MCSTRecipeListDeletage::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{// 调用基类的 sizeHint 方法获取原始大小QSize size = QStyledItemDelegate::sizeHint(option, index);// 修改高度为 50 像素size.setHeight(55);return size;
}bool MCSTRecipeListDeletage::editorEvent(QEvent* event,QAbstractItemModel* model,const QStyleOptionViewItem& option,const QModelIndex& index) 
{return MCSTRecipeListDeletage::editorEvent(event, model,option,index);
}

自定义ListView Item


#pragma execution_character_set("utf-8")
#ifndef MULTICHANNELTESTSYSTEM_MCSTLISTITEMWIDGET_H
#define MULTICHANNELTESTSYSTEM_MCSTLISTITEMWIDGET_H#include <QWidget>
#include "ui_MCSTRecipeListItemWidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MCSTRecipeListItemWidget; };
QT_END_NAMESPACEclass MCSTListItemWidget : public QWidget
{Q_OBJECTpublic:MCSTListItemWidget(QWidget *parent = nullptr);~MCSTListItemWidget();
public:void setRecipeName(const QString &);void setRecipeDate(const QString&);void setRecipeType(const QString&);void setRecipePath(const QString&);QString getRecipeName()const;QString getRecipeDate()const;QString getRecipeType()const;QString getRecipePath()const;
private:Ui::MCSTRecipeListItemWidget *ui;
private:QString m_recipePath;
};#include "MCSTListItemWidget.h"MCSTListItemWidget::MCSTListItemWidget(QWidget *parent): QWidget(parent), ui(new Ui::MCSTRecipeListItemWidget())
{ui->setupUi(this);
}MCSTListItemWidget::~MCSTListItemWidget()
{delete ui;
}void MCSTListItemWidget::setRecipeName(const QString& name)
{ui->lineEdit->setText(name);
}
void MCSTListItemWidget::setRecipeDate(const QString& date)
{ui->lineEdit_2->setText(date);
}
void MCSTListItemWidget::setRecipeType(const QString& Type)
{ui->label_3->setText(Type);
}
void MCSTListItemWidget::setRecipePath(const QString& path)
{m_recipePath = path;
}QString MCSTListItemWidget::getRecipeName()const
{return ui->lineEdit->text();
}
QString MCSTListItemWidget::getRecipeDate()const
{return ui->lineEdit_2->text();
}
QString MCSTListItemWidget::getRecipeType()const
{return ui->label_3->text();
}
QString MCSTListItemWidget::getRecipePath()const
{return m_recipePath;
}#endif

数据结构


class MCSTCalcSaveData : public QObject
{
Q_OBJECT
public:explicit MCSTCalcSaveData(QObject* parent = nullptr): QObject(parent){};~MCSTCalcSaveData() override = default;public:QVector<float> m_voltageData{};QVector<float> m_circuteData{};QVector<double> m_fzdData{};int m_modelId{};int m_channelId{};int m_dataType{-1};int m_sampleTime{-1};double m_powerData{0.00f};double m_deviceTempture{0.00};};
Q_DECLARE_METATYPE(QSharedPointer<MCSTCalcSaveData>)class MCSTRecipeDataInfoStr :public QObject 
{Q_OBJECT
public:explicit MCSTRecipeDataInfoStr(QObject* parent = nullptr) : QObject(parent) {};~MCSTRecipeDataInfoStr() override = default;public:int m_modelId;      //1001-1008int m_channelId;    //2001-2008QString m_selectFzdModel; //M1-M8float m_fzdAdjustFactor;float m_voltageLevel;float m_circuteLevel;float m_startVoltage;float m_finalVoltage;int m_ivScanTime;int m_ivTestInterval;int m_ivSamplePointCount;int m_mpptAdjustInterval;int m_testTotalTime;int m_channelEnable;
};
Q_DECLARE_METATYPE(MCSTRecipeDataInfoStr)
Q_DECLARE_METATYPE(QSharedPointer<MCSTRecipeDataInfoStr>)class MCSTRecipeConfigDataStr:public QObject
{Q_OBJECT
public:explicit MCSTRecipeConfigDataStr(QObject* parent = nullptr) : QObject(parent) {};~MCSTRecipeConfigDataStr() override = default;
public:bool isApply;QString m_recipeName;QString m_recipeModifyTime;QString m_recipeType;QString m_recipePath;//[1001,[2001,data]]--->[modelId,[channelId,data]]QMap<int, QMap<int, QSharedPointer<MCSTRecipeDataInfoStr>>> m_recipeDataInfoMap;};
Q_DECLARE_METATYPE(MCSTRecipeConfigDataStr)
Q_DECLARE_METATYPE(QSharedPointer<MCSTRecipeConfigDataStr>)

调用方法:

m_listModel = new MCSTRecipeListModel;m_listDelegate = new MCSTRecipeListDeletage;ui->listView->setModel(m_listModel);ui->listView->setItemDelegate(m_listDelegate);ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 禁用默认编辑QSharedPointer<MCSTRecipeConfigDataStr> recipeListItem(new MCSTRecipeConfigDataStr);    
if (recipeType == ActionType::IV)
{recipeListItem->m_recipeType = "IV";
}
else if (recipeType == ActionType::MPPT)
{recipeListItem->m_recipeType = "MPPT";
}
else if (recipeType == ActionType::IV_MPPT)
{recipeListItem->m_recipeType = "IV_MPPT";
}//创建 M1-M5 CH1-CH8的配方数据 现在默认是5*8 = 40个
for (auto model : model_codes)
{for (int index = 0;index <8;index++) {auto modelId = model;auto channelId = channel_codes[index];QSharedPointer<MCSTRecipeDataInfoStr> recipeDataInfo(new MCSTRecipeDataInfoStr);recipeDataInfo->m_modelId;      //1001-1008recipeDataInfo->m_channelId;    //2001-2008recipeDataInfo->m_selectFzdModel = "M1"; //M1-M8recipeDataInfo->m_fzdAdjustFactor = m_default_fzd_factor;recipeDataInfo->m_voltageLevel = test_voltage_level.first().toFloat();recipeDataInfo->m_circuteLevel = test_current_level.first().toFloat();recipeDataInfo->m_startVoltage = -1.0f;recipeDataInfo->m_finalVoltage = 1.0f;recipeDataInfo->m_ivScanTime = 100;   //msrecipeDataInfo->m_ivTestInterval = 3000; //msrecipeDataInfo->m_ivSamplePointCount = 30; //default 30recipeDataInfo->m_mpptAdjustInterval = 5 * 1000;//msrecipeDataInfo->m_testTotalTime = 1 * 60 * 60 * 1000; //msrecipeDataInfo->m_channelEnable = 0;QMap<int, QSharedPointer<MCSTRecipeDataInfoStr>> channelData;channelData[channelId] = recipeDataInfo;recipeListItem->m_recipeDataInfoMap[modelId] = channelData;}
}qDebug() << "createRecipe";recipeListItem->m_recipeName = tr("testRecipe");recipeListItem->m_recipeModifyTime = MCSTGenerateUUID::UUIDTime(); recipeListItem->m_recipePath = QString::fromStdString(MCSTData::getBinPath() + "/cache/"+recipeListItem->m_recipeName.toStdString() + ".json");m_listModel->insertData(recipeListItem);// 为新项启用持久编辑器    重中之重int row = m_listModel->rowCount();for (int i = 0; i < row; ++i) {ui->listView->openPersistentEditor(m_listModel->index(i));
}

以上就实现了下方的功能,左侧自定义listView,绑定右侧数据
在这里插入图片描述

http://www.xdnf.cn/news/65413.html

相关文章:

  • 【Redis】Jedis与Jedis连接池
  • Oracle数据库和PLSQL安装配置
  • 基于单片机的BMS热管理功能设计
  • 实验四 Java图形界面与事件处理
  • 如何对只能有一个`public`顶层类这句话的理解
  • 【解决】Vue + Vite + TS 配置路径别名成功仍爆红
  • Unreal Engine中FRotator与FQuat在赛车游戏方向盘控制中的协同应用解析
  • 【C++编程入门】:从零开始掌握基础语法
  • CENTOS 7 安装VNC
  • 【Java面试笔记:基础】1.谈谈你对Java平台的理解?
  • 移动端动态滑动拨盘选择器【Axure元件库】
  • 自注意力机制、多头自注意力机制、填充掩码 Python实现
  • 如何在白平衡标定种构建不同类型的白平衡色温坐标系
  • Android 音悦适配-v4.3.3-可在线播放可下载音乐的第三方APP
  • 【解决方法】关于解决QGC地面站4.4.3中文BUG,无法标注航点的问题
  • 模型检测技术的发展历史简介
  • Redis基础知识
  • 山东大学软件学院创新项目实训开发日志(21)之小问题修复之对话方向修改
  • 工厂模式:简单工厂模式
  • 免费送源码:ava+springboot+MySQL 基于springboot 宠物医院管理系统的设计与实现 计算机毕业设计原创定制
  • 修改IP地址能否精确到地级市的县?——全面解析
  • 第39讲|决策树与作物分布建模:可解释的AI助力农业智能推演
  • WINDOWS下使用命令行读取本地摄像头FFMPEG+DirectShow,ffplay直接播放摄像头数据
  • arkTs:使用Refresh实现下拉刷新功能(含状态提示与动画控制)
  • MySQL知识点讲解
  • n2n 搭建虚拟局域网,实现内网穿透
  • C++计算 n! 中末尾零的数量
  • RIP动态路由(三层交换机+单臂路由)
  • 20250421在荣品的PRO-RK3566开发板的Android13下频繁重启RKNPU fde40000.npu: Adding to iommu gr
  • Java学习路线--自用--带链接