概要
使用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() { } voidQRiceCheckBoxDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const { if(QVariant::Bool==index.data(Qt::DisplayRole).type())//如果数据类型为bool型,才绘制单选宽 { QStyleOptionButtoncheckBox; 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); } } boolQRiceCheckBoxDelegate::editorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index) { boolret=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); } returnret; } *>
QRiceButtonDelegate头文件
#ifndefQRICECHECKBOXDELEGATE_H #defineQRICECHECKBOXDELEGATE_H #include classQRiceCheckBoxDelegate:publicQItemDelegate { Q_OBJECT public: explicitQRiceCheckBoxDelegate(QObject*parent=nullptr); ~QRiceCheckBoxDelegate(); voidpaint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const; booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index); signals: }; #endif//QRICECHECKBOXDELEGATE_H
自定义表格中进度条ProgressBar委托 -- 创建QRiceProgressBarDelegate类继承QItemDelegate
重写paint方法和editorEvent方法,其中paint用于绘制,editorEvent用于处理用户输入
进度条其实采用进度条项样式(QStyleOptionProgressBar)绘制。
QRiceProgressBarDelegate源文件
voidQRiceProgressBarDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const { intprogress=index.data(Qt::DisplayRole).toInt(); QStyleOptionProgressBarprogressBar; 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);//绘制 } boolQRiceProgressBarDelegate::editorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index) { boolret=true; if(QEvent::MouseButtonDblClick!=event->type()) { ret=QItemDelegate::editorEvent(event,model,option,index); } returnret; }
QRiceProgressBarDelegate头文件
#ifndefQRICEPROGRESSBARDELEGATE_H #defineQRICEPROGRESSBARDELEGATE_H #include classQRiceProgressBarDelegate:publicQItemDelegate { Q_OBJECT public: explicitQRiceProgressBarDelegate(QObject*parent=nullptr); ~QRiceProgressBarDelegate(); voidpaint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const; booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index); signals: }; #endif//QRICEPROGRESSBARDELEGATE_H
自定义表格中按纽Button委托 -- 创建QRiceButtonDelegate类继承QItemDelegate
重写paint方法和editorEvent方法,其中paint用于绘制,editorEvent用于处理用户输入
按钮其实按钮项样式(QStyleOptionButton)绘制。
QRiceButtonDelegate源文件
voidQRiceButtonDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const { QStyleOptionButton*buttonStyle=buttonDelegate.value(index); if(!buttonStyle) { buttonStyle=newQStyleOptionButton();//创建按钮项样式 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);//绘制 } boolQRiceButtonDelegate::editorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&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("btn1column%1").arg(index.row()));//松开弹出消息框,显示对应行号 } } } returntrue; } voidQRiceButtonDelegate::showMsg(QStringstr) { QMessageBoxmsg; msg.setText(str); msg.exec(); }
QRiceButtonDelegate头文件
#ifndefQRICEBUTTONDELEGATE_H #defineQRICEBUTTONDELEGATE_H #include classQRiceButtonDelegate:publicQItemDelegate { Q_OBJECT public: explicitQRiceButtonDelegate(QObject*parent=nullptr); ~QRiceButtonDelegate(); voidpaint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const; booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index); signals: private: voidshowMsg(QStringstr); private: typedefQMapcollButtons; collButtonsbuttonDelegate; }; #endif//QRICEBUTTONDELEGATE_H ,>
创建一个自定义QRiceTableView类继承QTableView类
构造方法实现:①创建QStandardItemModel模型。②创建单选框委托到视图中。③创建进度条委托到视图第五列中。④创建按钮委托到视图第六列中。⑤设置表格视图的头部。
QRiceTableView::QRiceTableView(QWidget*parent): QTableView(parent) { horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); tableItemModel=newQStandardItemModel(); setModel(tableItemModel); tableCheckBoxDelegate=newQRiceCheckBoxDelegate(this); setItemDelegate(tableCheckBoxDelegate); tableProgressBarDelegate=newQRiceProgressBarDelegate(this); setItemDelegateForColumn(4,tableProgressBarDelegate); tableButtonDelegate=newQRiceButtonDelegate(this); setItemDelegateForColumn(5,tableButtonDelegate); QStringListtableHeaders; tableHeaders<< tr("Select") <"Name") << tr("Age") << tr("Work") << tr("Progress") << tr("Update"); tableItemModel->setHorizontalHeaderLabels(tableHeaders); } ,>(
在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中方法代码:
intQRiceTableView::QRiceTableGetRow(void) { returntableItemModel->rowCount(); } intQRiceTableView::QRiceTableGetColumn(void) { returntableItemModel->columnCount(); } voidQRiceTableView::QRiceTableAddItem(introw,structtableItemInfo*info) { QStandardItem*otaDeviceListStandardItem=tableItemModel->invisibleRootItem(); QStandardItem*checkBox=newQStandardItem(); QStandardItem*name=newQStandardItem(); QStandardItem*age=newQStandardItem(); QStandardItem*work=newQStandardItem(); 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); } voidQRiceTableView::QRiceTableSetProgress(introw,intProgress) { if(row< tableItemModel->rowCount()) { QModelIndexindex=tableItemModel->index(row,4); tableItemModel->setData(index,Progress,Qt::DisplayRole); } } voidQRiceTableView::QRiceTableSetSelect(introw,boolselect) { if(row< tableItemModel->rowCount()) { QModelIndexindex=tableItemModel->index(row,0); tableItemModel->setData(index,select,Qt::DisplayRole); } } boolQRiceTableView::QRiceTableGetSelect(introw) { if(row< tableItemModel->rowCount()) { QModelIndexindex=tableItemModel->index(row,0); returnindex.data(Qt::DisplayRole).toBool(); } returnfalse; } QStringQRiceTableView::QRiceTableGetString(introw,intcolumn) { if(row< tableItemModel->rowCount() &&column>0&&column< (tableItemModel->columnCount()-2)) { QModelIndexindex=tableItemModel->index(row,column); returnindex.data(Qt::DisplayRole).toString(); } return""; }
QRiceTableView头文件:
#ifndefQRICETABLEVIEW_H #defineQRICETABLEVIEW_H #include #include #include"qricecheckboxdelegate.h" #include"qriceprogressbardelegate.h" #include"qricebuttondelegate.h" classQRiceTableView:publicQTableView { Q_OBJECT public: structtableItemInfo { QStringname; QStringage; QStringwork; }; public: explicitQRiceTableView(QWidget*parent=nullptr); ~QRiceTableView(); signals: public: intQRiceTableGetRow(void); intQRiceTableGetColumn(void); voidQRiceTableAddItem(introw,structtableItemInfo*info); voidQRiceTableSetProgress(introw,intProgress); voidQRiceTableSetSelect(introw,boolselect); boolQRiceTableGetSelect(introw); QStringQRiceTableGetString(introw,intcolumn); 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(newUi::MainWindow) { ui->setupUi(this); setWindowTitle(tr("RiceDelegate")); structQRiceTableView::tableItemInfoinfo; 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=newQTimer(this); connect(timer,&QTimer::timeout,[=](){ staticintProgress1=0; staticintProgress2=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); }
界面中全选框的实现:
voidMainWindow::on_allCheckBox_clicked() { for(introw=0;row< ui->tableView->QRiceTableGetRow();row++) { if(ui->allCheckBox->checkState()==Qt::Checked) { ui->tableView->QRiceTableSetSelect(row,true); } else { ui->tableView->QRiceTableSetSelect(row,false); } } }
最终呈现结果:
-
嵌入式
+关注
关注
5068文章
19008浏览量
302995 -
ui
+关注
关注
0文章
204浏览量
21339 -
上位机
+关注
关注
27文章
930浏览量
54723 -
Qt
+关注
关注
1文章
301浏览量
37817
发布评论请先 登录
相关推荐
评论