Qt数据库应用14-超级自定义委托
一、前言
在QTableView、QTreeView以及对于衍生的QTableWidget、QTreeWidget类中,需要用到自定义委托的情形很多,比如提供下拉框选择,进度条展示下载进度啥的,默认的单元格是没有这些效果的,需要自己单独用委托的形式来展示,自定义委托一般有两种UI形式,一种是单元格一直显示对应的委托控件比如复选框、按钮、进度条等,一种是用户鼠标按下才显示对应的委托控件,鼠标离开自动恢复原有单元格的形式。
在设计这个委托类的时候,综合考虑了很多应用场景需求,例如复选框、文本框、下拉框、日期框、微调框、进度条等都支持,而且就合并在一个类中,方便直接new使用,通过函数指定不同的委托类型即可,也经过大量的项目实战应用,逐步完善到现在的程度。
自定义委托全家桶特点:
- 可设置多种委托类型,例如复选框、文本框、下拉框、日期框、微调框、进度条等。
- 可设置是否密文显示,一般用于文本框。
- 可设置是否允许编辑,一般用于下拉框。
- 可设置是否禁用,一般用来禁用某列。
- 可设置数据集合,比如下拉框数据集合。
- 提供值变化信号,比方说下拉框值改动触发。
- 可设置数据校验自动产生不同的图标。
- 支持设置校验列、校验规则、校验值、校验成功图标、校验失败图标、图标大小。
- 可设置校验数据产生不同的背景颜色和文字颜色。
- 校验规则支持 == > >= < <= != contains,非常丰富。
- 复选框自动居中而不是左侧,切换选中状态发送对应的信号。
- 可设置颜色委托,自动根据颜色值绘制背景颜色,自动设置最佳文本颜色。
- 可设置按钮委托,自动根据值生成多个按钮,按钮按下发送对应的信号。
- 当设置了委托列时自动绘制选中背景色和文字颜色。
- 可设置关键字对照表绘制关键字比如原始数据是 0-禁用 1-启用。
- 可设置复选框对应的映射选中不选中关键字。
- 根据不同的委托类型绘制,可以依葫芦画瓢自行增加自己的委托。
- 所有功能封装成1个类,核心代码不到500行,使用极其方便友好。
自定义委托全家桶应用场景:
- 某个字段需要提供下拉框进行选择,下拉框可选是否允许编辑。
- 某个字段需要提供密码框进行输入,密文显示字段值。
- 某个字段需要提供日期框下拉选择日期时间。
- 某个字段需要提供微调框设定值。
- 某个字段需要提供进度条显示字段值。
- 某个字段列需要禁用。
- 各种委托控件可以设置初始的数据集合,比如下拉框。
- 各种委托控件在值发生变化的时候发出valuechanged信号,比如下拉框选择声音文件的时候进行播放试听,微调框值改变的时候联动其他控件进行处理等。
- 某个字段根据设定的规则进行数据校验自动产生不同的图标显示,比如报警红色图标/正常绿色图标,一目了然。同时可设置校验列/校验规则/校验值/校验成功图标/校验失败图标/图标大小。
- 某个字段根据设定的规则进行数据校验自动绘制不同的背景颜色醒目显示,可设定规则包括 == > >= < <= != contains,可设置符合要求的内容文字颜色/背景颜色。
- 某个字段需要根据内容显示复选框(自动居中),比如内容是 0/禁用/false 等复选框不选中,1/启用/true 等复选框选中,具体选中不选中对应的内容可自定义。
- 某个字段需要根据内容重新替换显示成自定义的内容,比如值是0而需要显示成“不符合”字样,1显示成“符合”字样。对应的内容替换规则可设置关键字对照表。
- 某个字段需要根据颜色值显示对应的颜色,同时可以单击选中进行颜色选择。
- 某列需要显示操作按钮,按钮的个数/文字集合可设定,根据设定的文字集合平分宽度绘制按钮,单击某个按钮发送对应的按钮单击信号,带按钮索引以及行列,用于用户自行处理。
- 一个类通用所有需要委托的场景,相当于一个轮子用在所有项目中,不需要单独再去写不同的委托类。
- 一个类通用所有支持委托的控件,比如QTableView/QTableWidget/QListView/QTreeWidget/QListWidget等。
关于Qt数据库相关开发的一些经验总结:
https://qtchina.blog.csdn.net/article/details/119022424
二、功能特点
- 同时支持多种数据库比如odbc、sqlite、mysql、postgresql、sqlserver、oracle、人大金仓等。
- 一个数据库类即可管理本地数据库通信,也支持远程数据库通信等。
- 数据库线程支持执行各种sql语句,包括单条和批量。
- 组件中的所有类打印信息、错误信息、执行结果都信号发出去。
- 集成数据库通用翻页类(负责具体处理逻辑),搭配分页导航控件(负责外观),形成超级牛逼的翻页控件。
- 集成数据库自动清理类,设定最大记录数后台自动清理早期数据。
- 集成自定义委托类,支持复选框、文本框、下拉框、日期框、微调框、进度条等。
- 同时支持Qt4-Qt6,亲测Qt4.6到Qt6.3任意版本,任意系统和编译器。
- 本组件无故障 360天7乘24小时 运行在至少上万个现场,商业级别品质保证。
- 每个类都对应完整详细的使用示例,注释详细,非常适合阅读学习。
- 可以作为独立的程序运行,比如自动清理早期数据,同步数据到云端。
- 全部线程处理,不卡界面,自动重连数据库。
- 普通测试情况,sqlite数据库,数据库发生器每秒钟插入1000条记录约0.003秒钟,同时自动清理数据类每秒钟删除1000条记录约0.13秒,不同线程互不干扰。
三、体验地址
- 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_dbtool.zip
- 国内站点:https://gitee.com/feiyangqingyun
- 国际站点:https://github.com/feiyangqingyun
- 个人主页:https://blog.csdn.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
四、效果图

五、相关代码
#include "frmdbdelegate.h"
#include "ui_frmdbdelegate.h"
#include "quihelper.h"
#include "dbdelegate.h"
#include "dbconnthread.h"
frmDbDelegate::frmDbDelegate(QWidget *parent) : QWidget(parent), ui(new Ui::frmDbDelegate)
{
ui->setupUi(this);
this->initForm();
}
frmDbDelegate::~frmDbDelegate()
{
delete ui;
}
void frmDbDelegate::showEvent(QShowEvent *)
{
static bool isShow = false;
if (!isShow) {
isShow = true;
QTimer::singleShot(100, this, SLOT(initDb()));
QTimer::singleShot(500, this, SLOT(initData()));
}
}
void frmDbDelegate::initForm()
{
QUIHelper::initTableView(ui->tableView, 25, false, true);
//实例化数据库通信类
dbConn = new DbConnThread(this);
dbConn->setDbFlag("委托");
connect(dbConn, SIGNAL(debug(QString)), this, SLOT(debug(QString)));
connect(dbConn, SIGNAL(error(QString)), this, SLOT(error(QString)));
}
void frmDbDelegate::initDb()
{
DbInfo dbInfo;
//强制本程序带的数据库 dbtool.db
dbInfo.dbName = DbHelper::getDbDefaultFile();
dbConn->setConnInfo(DbHelper::getDbType("sqlite"), dbInfo);
if (!dbConn->openDb()) {
QUIHelper::showMessageBoxError("委托数据库打开失败!");
}
}
void frmDbDelegate::initData()
{
if (!dbConn->getOk()) {
return;
}
model = new QSqlTableModel(this);
model->setTable("UserInfo");
model->setSort(0, Qt::AscendingOrder);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
ui->tableView->setModel(model);
ui->tableView->setProperty("model", true);
QList<QString> columnNames;
columnNames << "用户名称" << "用户密码" << "用户类型" << "模块A" << "模块B" << "模块C" << "模块D" << "模块E" << "模块F" << "模块G" << "备注";
QList<int> columnWidths;
columnWidths << 100 << 120 << 80 << 60 << 60 << 60 << 60 << 60 << 60 << 60 << 60;
int count = columnNames.count();
for (int i = 0; i < count; i++) {
model->setHeaderData(i, Qt::Horizontal, columnNames.at(i));
ui->tableView->setColumnWidth(i, columnWidths.at(i));
}
//用户密码委托
DbDelegate *d_txt_userPwd = new DbDelegate(this);
d_txt_userPwd->setDelegateType("QLineEdit");
d_txt_userPwd->setDelegatePwd(true);
d_txt_userPwd->setDelegateColumn(1);
ui->tableView->setItemDelegateForColumn(1, d_txt_userPwd);
//用户类型委托
QStringList userType;
userType << "操作员" << "管理员";
DbDelegate *d_cbox_userType = new DbDelegate(this);
d_cbox_userType->setDelegateType("QComboBox");
d_cbox_userType->setDelegateValue(userType);
ui->tableView->setItemDelegateForColumn(2, d_cbox_userType);
//启用禁用委托
for (int i = 3; i < (3 + 7); i++) {
DbDelegate *d_ckbox_userAdmin = new DbDelegate(this);
d_ckbox_userAdmin->setDelegateColumn(i);
d_ckbox_userAdmin->setDelegateType("QCheckBox");
d_ckbox_userAdmin->setCheckBoxText("启用", "禁用");
ui->tableView->setItemDelegateForColumn(i, d_ckbox_userAdmin);
}
}
void frmDbDelegate::debug(const QString &msg)
{
}
void frmDbDelegate::error(const QString &msg)
{
}
void frmDbDelegate::on_btnAdd_clicked()
{
int count = model->rowCount();
model->insertRow(count);
QString userName = model->index(count - 1, 0).data().toString();
QString userPwd = model->index(count - 1, 1).data().toString();
QString userType = model->index(count - 1, 2).data().toString();
QString userAdmin1 = model->index(count - 1, 3).data().toString();
QString userAdmin2 = model->index(count - 1, 4).data().toString();
QString userAdmin3 = model->index(count - 1, 5).data().toString();
QString userAdmin4 = model->index(count - 1, 6).data().toString();
QString userAdmin5 = model->index(count - 1, 7).data().toString();
QString userAdmin6 = model->index(count - 1, 8).data().toString();
QString userAdmin7 = model->index(count - 1, 9).data().toString();
QString userMark = model->index(count - 1, 10).data().toString();
//设置新增加的行默认值
model->setData(model->index(count, 0), userName);
model->setData(model->index(count, 1), userPwd);
model->setData(model->index(count, 2), userType);
model->setData(model->index(count, 3), userAdmin1);
model->setData(model->index(count, 4), userAdmin2);
model->setData(model->index(count, 5), userAdmin3);
model->setData(model->index(count, 6), userAdmin4);
model->setData(model->index(count, 7), userAdmin5);
model->setData(model->index(count, 8), userAdmin6);
model->setData(model->index(count, 9), userAdmin7);
model->setData(model->index(count, 10), userMark);
ui->tableView->setCurrentIndex(model->index(count, 0));
}
void frmDbDelegate::on_btnSave_clicked()
{
model->database().transaction();
if (model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
qDebug() << TIMEMS << model->database().lastError();
QUIHelper::showMessageBoxError("保存信息失败,请重新填写!");
}
//有些数据库需要主动查询一下不然是空白的比如odbc数据源
model->select();
}
void frmDbDelegate::on_btnDelete_clicked()
{
int row = ui->tableView->currentIndex().row();
if (row < 0) {
QUIHelper::showMessageBoxError("请选择要删除的用户!");
return;
}
if (QUIHelper::showMessageBoxQuestion("确定要删除该用户吗? 删除后不能恢复!") == QMessageBox::Yes) {
QString userName = model->index(row, 0).data().toString();
if (userName == "admin") {
QUIHelper::showMessageBoxError("管理员 [admin] 不能被删除!", 3);
return;
}
model->removeRow(row);
model->submitAll();
ui->tableView->setCurrentIndex(model->index(model->rowCount() - 1, 0));
}
}
void frmDbDelegate::on_btnReturn_clicked()
{
model->revertAll();
}
void frmDbDelegate::on_btnClear_clicked()
{
if (model->rowCount() <= 0) {
return;
}
if (QUIHelper::showMessageBoxQuestion("确定要清空所有用户信息吗?") == QMessageBox::Yes) {
DbHelper::clearTable("UserInfo", AppConfig::LocalDbType);
model->select();
}
}
Qt数据库应用14-超级自定义委托的更多相关文章
- Qt自定义委托在QTableView中绘制控件、图片、文字(内容比较全)
自定义委托,继承于,QStyledItemDelegate类,重载Paint()函数, 1.实现在QTableView中绘制 格式字符串 2.实现在QTableView中绘制进度条 3.实现在QTab ...
- Qt自定义委托在QTableView中绘制控件、图片、文字
自定义委托,继承于,QStyledItemDelegate类,重载Paint()函数, 1.实现在QTableView中绘制 格式字符串 2.实现在QTableView中绘制进度条 3.实现在QTab ...
- 26.QT-模型视图之自定义委托
在上一章学习 25.QT-模型视图 后,本章接着学习视图委托 视图委托(Delegate)简介 由于模型负责组织数据,而视图负责显示数据,所以当用户想修改显示的数据时,就要通过视图中的委托来完成 视图 ...
- jdbc 加载数据库驱动如何破坏双亲委托模式
导读 通过jdbc链接数据库,是每个学习Java web 方向的人必然一开始会写的代码,虽然现在各路框架都帮大家封装好了jdbc,但是研究一下jdbc链接的套路还是很意义 术语以及相 ...
- Qt之模型/视图(自定义风格)
Qt之模型/视图(自定义风格) 关于自定义风格是针对视图与委托而言的,使用事件与QSS都可以进行处理,今天关于美化的细节讲解一下. 先看下图: 先撇开界面的美观性(萝卜青菜,各有所爱),就现有的这些风 ...
- QTableWidget自定义委托
QTableWidget单元格使用自定义的lineEdit控件导致不能选中 使用自定义委托解决 1.自定义委托 class LineEditDelegate : public QItemDelegat ...
- 自定义委托类型 - .Net自带委托类型
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...
- EventHandler委托与自定义委托
http://blog.csdn.net/uuxyz/article/details/7175248 EventHandler委托与自定义委托 自定义委托: //1. public delegate ...
- qt数据库多线程问题的解决(QSqlDatabase只能在创建它的线程中使用)
Qt数据库由QSqlDatabase::addDatabase()生成的QSqlDatabase只能在创建它的线程中使用, 在多线程中共用连接或者在另外一个线程中创建query都是不支持的几乎国内没有 ...
- Java数据库设计14个技巧
Java数据库设计14个技巧 1. 原始单据与实体之间的关系 可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体.在特殊情况下,它们可能是一对 ...
随机推荐
- 云原生周刊:Docker 推出 Docker Build Cloud
开源项目推荐 Kube-Vip Kube-Vip 旨在为 Kubernetes 集群提供高可用性和负载均衡功能.它提供了一个可插拔的 VIP(虚拟 IP)管理器,可以为集群中的服务分配一个虚拟 IP ...
- 为什么说Kafka还不是完美的实时数据通道
本文主要谈谈Kafka用于实时数据通道场景的缺陷,以及如何在架构上进行弥补. Kafka归属于消息队列类产品,其他竞品还有RabbitMQ.RocketMQ等,总的来说它们都是基于生产者.中介和消费者 ...
- JS转义html编码
两个方法: 1.利用用浏览器内部转换器实现html转义: 2.用正则表达式实现html转义: var HtmlUtil = { /*1.用浏览器内部转换器实现html编码(转义)*/ htmlEnco ...
- SSAS部署失败方法总结
最近在自学SSAS,从最简单的入手,却频频遇到问题,为了以后在学习过程中能更快的进行问题的定位,所以在此将遇到的问题以及解决方案进行记录 Q1:数据源"Adventure Works DW2 ...
- 2.17 新手必看的Linux服务器管理和维护注意事项
本节介绍有关服务器管理和维护过程中的一些注意事项,都是笔者的经验之谈,相信对新手会有一定的启发和帮助. 很多初学者接触Linux 时间不长,还未完整地学习一遍 Linux,理解本节内容可能有些困难,可 ...
- LVM 使用与扩容总结
转载请注明出处: LVM(Logical Volume Manager,逻辑卷管理器)是一个用于Linux系统的磁盘管理工具.它提供了一种更加灵活的存储管理机制,可以方便地进行磁盘的扩容.缩减.快照以 ...
- 题解:CF559B Equivalent Strings
CF559B Equivalent Strings 题解 题目描述 吐槽一下,题目翻译有歧义. 思路分析 你会发现,当你需要判断字符串 \(a,b\) 是否等价时,如果长度为偶数,需要继续判断字符串 ...
- Java灵魂拷问13个为什么,你都会哪些?
大家好,我是 V 哥.今天看了阿里云开发者社区关于 Java 的灵魂拷问,一线大厂在用 Java 时,都会考虑哪些问题呢,对于工作多年,又没有大厂经历的小伙伴不妨看看,V 哥总结的这13个为什么,你都 ...
- delphi Image32 图像采样
图像数据采样 代码: 1 unit uFrmImageResampling; 2 3 interface 4 5 uses 6 Winapi.Windows, Winapi.Messages, Win ...
- 【一步步开发AI运动小程序】十六、AI运动识别中,如何判断人体站位?
[云智AI运动识别小程序插件],可以为您的小程序,赋于人体检测识别.运动检测识别.姿态识别检测AI能力.本地原生识别引擎,无需依赖任何后台或第三方服务,有着识别速度快.体验佳.扩展性强.集成快.成本低 ...