Qt自定义委托--实现批量升级UI

概要
使用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上提供支持
人工智能在出行领域有什么新成就