概要
使用Qt編寫上位機(jī)是一個(gè)非常不錯(cuò)的選擇,簡(jiǎn)單說一下作者的看法:
①Q(mào)t采用的是C++,所以在某種程度上與嵌入式設(shè)備數(shù)據(jù)類型兼容,所以嵌入式設(shè)備與上位機(jī)間的協(xié)議定義數(shù)據(jù)結(jié)構(gòu)等都可以相互套用,
②Qt是跨平臺(tái)的,所以代碼開發(fā)一次,多平臺(tái)運(yùn)行。
③Qt學(xué)習(xí)成本低,網(wǎng)上資料很多,基本你遇到的問題,網(wǎng)上都能找到。
對(duì)于嵌入式開發(fā)者來說,會(huì)寫上位機(jī)可以提高開發(fā)效率,比如可以開發(fā)抓包工具,日志數(shù)據(jù)分析,升級(jí)(網(wǎng)絡(luò)升級(jí),串口升級(jí)等)
說到升級(jí),那么就有些場(chǎng)景,比如批量升級(jí),某臺(tái)升級(jí)等需求。有這些需求那么就要有對(duì)應(yīng)的UI呈現(xiàn)給用戶。所以Qt的自定義委托在這種場(chǎng)景顯的尤為重要。
Qt模型視圖中的委托
Qt模型視圖采用類MVC框架,那什么是MVC框架?
M--模型:負(fù)責(zé)組織數(shù)據(jù)
V--試圖:負(fù)責(zé)顯示數(shù)據(jù)
C--控制:負(fù)責(zé)用戶輸入
Qt模型視圖設(shè)計(jì):①視圖中集成了處理用戶輸入的功能,②視圖將用戶輸入作為內(nèi)部獨(dú)立的子功能實(shí)現(xiàn)
模型視圖中的委托:①委托是視圖中處理用戶輸入的部件。②視圖可以設(shè)置委托對(duì)象用于用戶輸入。③委托對(duì)象負(fù)責(zé)創(chuàng)建和顯示用戶輸入上下文。
Qt 自定義委托--實(shí)現(xiàn)批量升級(jí)UI
準(zhǔn)備工作:下載Qt工具,然后創(chuàng)建一個(gè)基類為QMainWindow的工程,并且?guī)i的。
設(shè)計(jì)一個(gè)ui,一個(gè)CheckBox控件和TableView控件
自定義表格中單選框CheckBox委托 -- 創(chuàng)建QRiceButtonDelegate類繼承QItemDelegate
重寫paint方法和editorEvent方法,其中paint用于繪制,editorEvent用于處理用戶輸入
單選框其實(shí)使用按鈕項(xiàng)樣式(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())//如果數(shù)據(jù)類型為bool型,才繪制單選寬 { QStyleOptionButtoncheckBox; checkBox.state=index.data().toBool()?QStyle::State_On:QStyle::State_Off;//繪制后的默認(rèn)狀態(tài) checkBox.state|=QStyle::State_Enabled; checkBox.rect=option.rect; checkBox.rect.setX(option.rect.x()+option.rect.width()/2-6);//設(shè)置在表格中的顯示位置 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);//更新模型數(shù)據(jù) } } 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
自定義表格中進(jìn)度條ProgressBar委托 -- 創(chuàng)建QRiceProgressBarDelegate類繼承QItemDelegate
重寫paint方法和editorEvent方法,其中paint用于繪制,editorEvent用于處理用戶輸入
進(jìn)度條其實(shí)采用進(jìn)度條項(xiàng)樣式(QStyleOptionProgressBar)繪制。
QRiceProgressBarDelegate源文件
voidQRiceProgressBarDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const { intprogress=index.data(Qt::DisplayRole).toInt(); QStyleOptionProgressBarprogressBar; progressBar.minimum=0;//設(shè)置進(jìn)度條最小值 progressBar.maximum=100;//設(shè)置進(jìn)度條最大值 progressBar.progress=progress;//設(shè)置繪制后的數(shù)值 progressBar.rect=option.rect.adjusted(4,4,-4,-4);//設(shè)置進(jìn)度條的大小 progressBar.textVisible=true;//設(shè)置進(jìn)度條顯示數(shù)值 progressBar.textAlignment=Qt::AlignCenter;//設(shè)置進(jìn)度條數(shù)值顯示位置 progressBar.text=QString("%1%").arg(progress);//設(shè)置進(jìn)度條數(shù)值顯示 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委托 -- 創(chuàng)建QRiceButtonDelegate類繼承QItemDelegate
重寫paint方法和editorEvent方法,其中paint用于繪制,editorEvent用于處理用戶輸入
按鈕其實(shí)按鈕項(xiàng)樣式(QStyleOptionButton)繪制。
QRiceButtonDelegate源文件
voidQRiceButtonDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const { QStyleOptionButton*buttonStyle=buttonDelegate.value(index); if(!buttonStyle) { buttonStyle=newQStyleOptionButton();//創(chuàng)建按鈕項(xiàng)樣式 buttonStyle->text="Update";//設(shè)置按鈕中顯示的內(nèi)容 buttonStyle->state|=QStyle::State_Enabled;//設(shè)置按鈕中的狀態(tài) (const_cast(this))->buttonDelegate.insert(index,buttonStyle); } buttonStyle->rect=option.rect.adjusted(4,4,-4,-4);//設(shè)置按鈕的大小 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)//按鈕按下,設(shè)置按鈕的狀態(tài) { 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)//按鈕松開,設(shè)置按鈕的狀態(tài) { 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()));//松開彈出消息框,顯示對(duì)應(yīng)行號(hào) } } } 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 ,>
創(chuàng)建一個(gè)自定義QRiceTableView類繼承QTableView類
構(gòu)造方法實(shí)現(xiàn):①創(chuàng)建QStandardItemModel模型。②創(chuàng)建單選框委托到視圖中。③創(chuàng)建進(jìn)度條委托到視圖第五列中。④創(chuàng)建按鈕委托到視圖第六列中。⑤設(shè)置表格視圖的頭部。
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<setHorizontalHeaderLabels(tableHeaders); } ,>(
在QRiceTableView中實(shí)現(xiàn)用戶使用方法:
方法 | 說明 |
---|---|
int QRiceTableGetRow(void); | 獲取列表行數(shù) |
int QRiceTableGetColumn(void); | 獲取列表列數(shù) |
void QRiceTableAddItem(int row, struct tableItemInfo *info); | 增加一行 |
void QRiceTableSetProgress(int row, int Progress); | 設(shè)置某行的進(jìn)度條 |
void QRiceTableSetSelect(int row, bool select); | 單選框狀態(tài)設(shè)置 |
bool QRiceTableGetSelect(int row); | 單選框狀態(tài)獲取 |
QString QRiceTableGetString(int row, int column); | 獲取某行某列的數(shù)據(jù) |
在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(rowrowCount()) { QModelIndexindex=tableItemModel->index(row,4); tableItemModel->setData(index,Progress,Qt::DisplayRole); } } voidQRiceTableView::QRiceTableSetSelect(introw,boolselect) { if(rowrowCount()) { QModelIndexindex=tableItemModel->index(row,0); tableItemModel->setData(index,select,Qt::DisplayRole); } } boolQRiceTableView::QRiceTableGetSelect(introw) { if(rowrowCount()) { QModelIndexindex=tableItemModel->index(row,0); returnindex.data(Qt::DisplayRole).toBool(); } returnfalse; } QStringQRiceTableView::QRiceTableGetString(introw,intcolumn) { if(rowrowCount() &&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控件,選擇提升為:
填寫對(duì)應(yīng)類名,類的頭文件相對(duì)路徑:
點(diǎn)擊添加后,然后點(diǎn)擊提升按鈕,就完成了控件的提升
在mainwindow.cpp中增加測(cè)試用例:
在構(gòu)造方法中,創(chuàng)建兩條數(shù)據(jù),并且啟動(dòng)一個(gè)定時(shí)器刷新進(jìn)度條:
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("公務(wù)員"); 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); }
界面中全選框的實(shí)現(xiàn):
voidMainWindow::on_allCheckBox_clicked() { for(introw=0;rowtableView->QRiceTableGetRow();row++) { if(ui->allCheckBox->checkState()==Qt::Checked) { ui->tableView->QRiceTableSetSelect(row,true); } else { ui->tableView->QRiceTableSetSelect(row,false); } } }
最終呈現(xiàn)結(jié)果:
-
嵌入式
+關(guān)注
關(guān)注
5059文章
18973瀏覽量
302042 -
ui
+關(guān)注
關(guān)注
0文章
203瀏覽量
21330 -
上位機(jī)
+關(guān)注
關(guān)注
27文章
930瀏覽量
54696 -
Qt
+關(guān)注
關(guān)注
1文章
301瀏覽量
37786
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論