概要
使用qt编写上位机是一个非常不错的选择,简单说一下作者的看法:
①qt采用的是c++,所以在某种程度上与嵌入式设备数据类型兼容,所以嵌入式设备与上位机间的协议定义数据结构等都可以相互套用,
②qt是跨平台的,所以代码开发一次,多平台运行。
③qt学习成本低,网上资料很多,基本你遇到的问题,网上都能找到。
对于嵌入式开发者来说,会写上位机可以提高开发效率,比如可以开发抓包工具,日志数据分析,升级(网络升级,串口升级等)
说到升级,那么就有些场景,比如批量升级,某台升级等需求。有这些需求那么就要有对应的ui呈现给用户。所以qt的自定义委托在这种场景显的尤为重要。
qt模型视图中的委托
qt模型视图采用类mvc框架,那什么是mvc框架?
m--模型:负责组织数据
v--试图:负责显示数据
c--控制:负责用户输入
qt模型视图设计:①视图中集成了处理用户输入的功能,②视图将用户输入作为内部独立的子功能实现
模型视图中的委托:①委托是视图中处理用户输入的部件。②视图可以设置委托对象用于用户输入。③委托对象负责创建和显示用户输入上下文。
qt 自定义委托--实现批量升级ui
准备工作:下载qt工具,然后创建一个基类为qmainwindow的工程,并且带ui的。
设计一个ui,一个checkbox控件和tableview控件
自定义表格中单选框checkbox委托 -- 创建qricebuttondelegate类继承qitemdelegate
重写paint方法和editorevent方法,其中paint用于绘制,editorevent用于处理用户输入
单选框其实使用按钮项样式(qstyleoptionbutton)绘制。
qricebuttondelegate源文件
#include qricecheckboxdelegate.h#include #include #include #include #include qricecheckboxdelegate::qricecheckboxdelegate(qobject *parent) : qitemdelegate(parent){}qricecheckboxdelegate::~qricecheckboxdelegate(){}void qricecheckboxdelegate::paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const{ if(qvariant::bool == index.data(qt::displayrole).type()) //如果数据类型为bool型,才绘制单选宽 { qstyleoptionbutton checkbox; checkbox.state = index.data().tobool() ? qstyle::state_on : qstyle::state_off; //绘制后的默认状态 checkbox.state |= qstyle::state_enabled; checkbox.rect = option.rect; checkbox.rect.setx(option.rect.x() + option.rect.width()/2 - 6); //设置在表格中的显示位置 qapplication::style()->drawcontrol(qstyle::ce_checkbox, &checkbox, painter); // 绘制 } else { qitemdelegate::paint(painter, option, index); }}bool qricecheckboxdelegate::editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index){ bool ret = true; if(qvariant::bool == index.data().type()) { qmouseevent* mouse = dynamic_cast(event); if( (null != mouse) && (qevent::mousebuttonpress == mouse->type()) && (option.rect.contains(mouse->pos())) ) { model->setdata(index, !index.data().tobool(), qt::displayrole); // 更新模型数据 } } else { ret = qitemdelegate::editorevent(event, model, option, index); } return ret;}*>
qricebuttondelegate头文件
#ifndef qricecheckboxdelegate_h#define qricecheckboxdelegate_h#include class qricecheckboxdelegate : public qitemdelegate{ q_objectpublic: explicit qricecheckboxdelegate(qobject *parent = nullptr); ~qricecheckboxdelegate(); void paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const; bool editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index);signals:};#endif // qricecheckboxdelegate_h
自定义表格中进度条progressbar委托 -- 创建qriceprogressbardelegate类继承qitemdelegate
重写paint方法和editorevent方法,其中paint用于绘制,editorevent用于处理用户输入
进度条其实采用进度条项样式(qstyleoptionprogressbar)绘制。
qriceprogressbardelegate源文件
void qriceprogressbardelegate::paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const{ int progress = index.data(qt::displayrole).toint(); qstyleoptionprogressbar progressbar; progressbar.minimum = 0; //设置进度条最小值 progressbar.maximum = 100; //设置进度条最大值 progressbar.progress = progress; //设置绘制后的数值 progressbar.rect = option.rect.adjusted(4, 4, -4, -4); //设置进度条的大小 progressbar.textvisible = true; //设置进度条显示数值 progressbar.textalignment = qt::aligncenter; //设置进度条数值显示位置 progressbar.text = qstring(%1%).arg(progress); //设置进度条数值显示 qapplication::style()->drawcontrol(qstyle::ce_progressbar, &progressbar, painter); // 绘制}bool qriceprogressbardelegate::editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index){ bool ret = true; if(qevent::mousebuttondblclick != event->type()) { ret = qitemdelegate::editorevent(event, model, option, index); } return ret;}
qriceprogressbardelegate头文件
#ifndef qriceprogressbardelegate_h#define qriceprogressbardelegate_h#include class qriceprogressbardelegate : public qitemdelegate{ q_objectpublic: explicit qriceprogressbardelegate(qobject *parent = nullptr); ~qriceprogressbardelegate(); void paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const; bool editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index);signals:};#endif // qriceprogressbardelegate_h
自定义表格中按纽button委托 -- 创建qricebuttondelegate类继承qitemdelegate
重写paint方法和editorevent方法,其中paint用于绘制,editorevent用于处理用户输入
按钮其实按钮项样式(qstyleoptionbutton)绘制。
qricebuttondelegate源文件
void qricebuttondelegate::paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const{ qstyleoptionbutton *buttonstyle = buttondelegate.value(index); if(!buttonstyle) { buttonstyle = new qstyleoptionbutton(); // 创建按钮项样式 buttonstyle->text = update; // 设置按钮中显示的内容 buttonstyle->state |= qstyle::state_enabled; // 设置按钮中的状态 (const_cast(this))->buttondelegate.insert(index, buttonstyle); } buttonstyle->rect = option.rect.adjusted(4, 4, -4, -4); //设置按钮的大小 painter->save(); if (option.state & qstyle::state_selected) { painter->fillrect(option.rect, option.palette.highlight()); } painter->restore(); qapplication::style()->drawcontrol(qstyle::ce_pushbutton, buttonstyle, painter); //绘制}bool qricebuttondelegate::editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index){ q_unused(model); q_unused(option); qmouseevent *mouseevent = (qmouseevent *)event; if(event->type() == qevent::mousebuttonpress) // 按钮按下,设置按钮的状态 { if(buttondelegate.contains(index)) { qstyleoptionbutton *buttonstyle = buttondelegate.value(index); if(buttonstyle->rect.contains(mouseevent->x(), mouseevent->y())) { buttonstyle->state |= qstyle::state_sunken; } } } if(event->type() == qevent::mousebuttonrelease) // 按钮松开,设置按钮的状态 { if(buttondelegate.contains(index)) { qstyleoptionbutton *buttonstyle = buttondelegate.value(index); if(buttonstyle->rect.contains(mouseevent->x(), mouseevent->y())) { buttonstyle->state &= (~qstyle::state_sunken); showmsg(tr(btn1 column %1).arg(index.row())); // 松开弹出消息框,显示对应行号 } } } return true;}void qricebuttondelegate::showmsg(qstring str){ qmessagebox msg; msg.settext(str); msg.exec();}
qricebuttondelegate头文件
#ifndef qricebuttondelegate_h#define qricebuttondelegate_h#include class qricebuttondelegate : public qitemdelegate{ q_objectpublic: explicit qricebuttondelegate(qobject *parent = nullptr); ~qricebuttondelegate(); void paint(qpainter *painter, const qstyleoptionviewitem &option, const qmodelindex &index) const; bool editorevent(qevent *event, qabstractitemmodel *model, const qstyleoptionviewitem &option, const qmodelindex &index);signals:private: void showmsg(qstring str);private: typedef qmap collbuttons; collbuttons buttondelegate;};#endif // qricebuttondelegate_h,>
创建一个自定义qricetableview类继承qtableview类
构造方法实现:①创建qstandarditemmodel模型。②创建单选框委托到视图中。③创建进度条委托到视图第五列中。④创建按钮委托到视图第六列中。⑤设置表格视图的头部。
qricetableview::qricetableview(qwidget *parent) : qtableview(parent){ horizontalheader()->setsectionresizemode(qheaderview::stretch); tableitemmodel = new qstandarditemmodel(); setmodel(tableitemmodel); tablecheckboxdelegate = new qricecheckboxdelegate(this); setitemdelegate(tablecheckboxdelegate); tableprogressbardelegate = new qriceprogressbardelegate(this); setitemdelegateforcolumn(4, tableprogressbardelegate); tablebuttondelegate = new qricebuttondelegate(this); setitemdelegateforcolumn(5, tablebuttondelegate); qstringlist tableheaders; tableheaders << tr(select)
在qricetableview中实现用户使用方法:
方法 说明
int qricetablegetrow(void); 获取列表行数
int qricetablegetcolumn(void); 获取列表列数
void qricetableadditem(int row, struct tableiteminfo *info); 增加一行
void qricetablesetprogress(int row, int progress); 设置某行的进度条
void qricetablesetselect(int row, bool select); 单选框状态设置
bool qricetablegetselect(int row); 单选框状态获取
qstring qricetablegetstring(int row, int column); 获取某行某列的数据
在qricetableview中方法代码:
int qricetableview::qricetablegetrow(void){ return tableitemmodel->rowcount();}int qricetableview::qricetablegetcolumn(void){ return tableitemmodel->columncount();}void qricetableview::qricetableadditem(int row, struct tableiteminfo *info){ qstandarditem* otadeviceliststandarditem = tableitemmodel->invisiblerootitem(); qstandarditem *checkbox = new qstandarditem(); qstandarditem *name = new qstandarditem(); qstandarditem *age = new qstandarditem(); qstandarditem *work = new qstandarditem(); checkbox->setdata(false, qt::displayrole); name->setdata(info->name, qt::displayrole); age->setdata(info->age, qt::displayrole); work->setdata(info->work, qt::displayrole); otadeviceliststandarditem->setchild(row, 0, checkbox); otadeviceliststandarditem->setchild(row, 1, name); otadeviceliststandarditem->setchild(row, 2, age); otadeviceliststandarditem->setchild(row, 3, work);}void qricetableview::qricetablesetprogress(int row, int progress){ if(row rowcount()) { qmodelindex index = tableitemmodel->index(row, 4); tableitemmodel->setdata(index, progress, qt::displayrole); }}void qricetableview::qricetablesetselect(int row, bool select){ if(row rowcount()) { qmodelindex index = tableitemmodel->index(row, 0); tableitemmodel->setdata(index, select, qt::displayrole); }}bool qricetableview::qricetablegetselect(int row){ if(row rowcount()) { qmodelindex index = tableitemmodel->index(row, 0); return index.data(qt::displayrole).tobool(); } return false;}qstring qricetableview::qricetablegetstring(int row, int column){ if(row rowcount() && column > 0 && column columncount() - 2)) { qmodelindex index = tableitemmodel->index(row, column); return index.data(qt::displayrole).tostring(); } return ;}
qricetableview头文件:
#ifndef qricetableview_h#define qricetableview_h#include #include #include qricecheckboxdelegate.h#include qriceprogressbardelegate.h#include qricebuttondelegate.hclass qricetableview : public qtableview{ q_objectpublic: struct tableiteminfo { qstring name; qstring age; qstring work; };public: explicit qricetableview(qwidget *parent = nullptr); ~qricetableview();signals:public: int qricetablegetrow(void); int qricetablegetcolumn(void); void qricetableadditem(int row, struct tableiteminfo *info); void qricetablesetprogress(int row, int progress); void qricetablesetselect(int row, bool select); bool qricetablegetselect(int row); qstring qricetablegetstring(int row, int column);private: qstandarditemmodel *tableitemmodel; qricecheckboxdelegate *tablecheckboxdelegate; qriceprogressbardelegate *tableprogressbardelegate; qricebuttondelegate *tablebuttondelegate;};#endif // qricetableview_h
将ui中的qtableview提升为qricetableview:
右击qtableview控件,选择提升为:
填写对应类名,类的头文件相对路径:
点击添加后,然后点击提升按钮,就完成了控件的提升
在mainwindow.cpp中增加测试用例:
在构造方法中,创建两条数据,并且启动一个定时器刷新进度条:
mainwindow::mainwindow(qwidget *parent) : qmainwindow(parent) , ui(new ui::mainwindow){ ui->setupui(this); setwindowtitle(tr(rice delegate)); struct qricetableview::tableiteminfo info; info.name = tr(ricechen); info.age = tr(18); info.work = tr(程序员); ui->tableview->qricetableadditem(0, &info); info.name = tr(米饭); info.age = tr(20); info.work = tr(公务员); ui->tableview->qricetableadditem(1, &info); qtimer * timer = new qtimer(this); connect(timer,&qtimer::timeout,[=](){ static int progress1 = 0; static int progress2 = 0; ui->tableview->qricetablesetprogress(0, progress1); ui->tableview->qricetablesetprogress(1, progress2); progress1 += 1; progress2 += 2; if(progress1 > 100) { progress1 = 0; } if(progress2 > 100) { progress2 = 0; } }); timer->start(1000);}
界面中全选框的实现:
void mainwindow::on_allcheckbox_clicked(){ for(int row = 0; row tableview->qricetablegetrow(); row++) { if(ui->allcheckbox->checkstate() == qt::checked) { ui->tableview->qricetablesetselect(row, true); } else { ui->tableview->qricetablesetselect(row, false); } }}
最终呈现结果:
新型指纹识别传感器的应用解析
TCL通讯全线4G终端亮相巴塞罗那MWC2014
Silicon Labs的Unify SDK凭借“一次设计,全部支持”的强大功能实现物联网无线连接技术的突破性进展
电池电量指示器DIY图解
三相隔离变压器原理
Qt自定义委托--实现批量升级UI
3D打印技术虽然发展迅速,但还不能取代传统制造技术
SI24R2E校园学生卡有源标签2.4G物联网有源RFID标签芯片方案
物联网在教育领域中的应用有哪些
VRgineers推出新版8K超宽XTAL头显 可将头显连接到模拟器应用头盔
萨瑞电子株式会社宣布推出三款微控制器的新型目标板
电磁炉烧保险管的原因分析
新年礼物买什么好,不如看看运动最搭的骨传导耳机
数码相机伴侣兼容存储卡种类
售价相差500元,定位不同,vivo新旗舰vivoX9s Plus和小米6,你选择谁
安森美推出电感型位置传感器,可替代光学编码器
一文了解pcb价格构成因素
魅族科技宣布将于本月底在Indiegogo上线魅族zero的众筹
三星10nm工艺技术已经在Galaxy S8上提供支持
人工智能在出行领域有什么新成就