日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt官方文档阅读笔记-对官方Star Delegate Example实例的解析

發(fā)布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt官方文档阅读笔记-对官方Star Delegate Example实例的解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

對應(yīng)的博文為:

?

目錄

Star Delegate Example

StarDelegate Class Definition

StarDelegate Class Implementation

StarEditor Class Definition

StarEditor Class Implementation

StarRating Class Definition

StarRating Class Implementation

The main() Function

Possible Extensions and Suggestions


?

Star Delegate Example

在QListView、QTableView、QTreeView這些控件里面如果要有個性化的item就得使用委托,委托在編輯item的時候讓這些個性化的東西放置于最頂部。

這里告訴了一個道理當(dāng)要自定義數(shù)據(jù)類型(比如int和QString混合,或者XX:xx這種數(shù)據(jù))或者想定制渲染或者編輯存在的數(shù)據(jù),就要子類化QAbstractItemDelegate或QItemDelegate(這兩個的優(yōu)劣我就不說了,看名字大家都知道了)。

Star Delegate Example 這個栗子就是來教我們怎么去渲染(我覺得這個應(yīng)該叫渲染)和編輯一個打分的數(shù)據(jù)類型(就是用星星表示的)

這個栗子包含了3個類(官方文檔就是清楚):
1.StarRating:自定義數(shù)據(jù)類型類,就是存那幾個星星;
2.StarDelegate:繼承于QItemDelegate,提供打分的功能,并且就是這個StarDelegate通過繼承QItemDelegate實現(xiàn)數(shù)據(jù)類型(那幾個星星)的處理;
3.StarEditor:繼承于QWidget,也是被StarDelegate使用的,這吊玩意提供了讓用戶使用鼠標(biāo)去編輯“星星”;

?

StarDelegate Class Definition

class StarDelegate : public QStyledItemDelegate{Q_OBJECTpublic:StarDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;private slots:void commitAndCloseEditor();};

關(guān)鍵:重寫了公有虛函數(shù),實現(xiàn)了自定義渲染和編輯;

?

StarDelegate Class Implementation


首先是paint()函數(shù),這個是父類的,目的是讓視圖重畫item:

void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const{if (index.data().canConvert<StarRating>()) {StarRating starRating = qvariant_cast<StarRating>(index.data());if (option.state & QStyle::State_Selected)painter->fillRect(option.rect, option.palette.highlight());starRating.paint(painter, option.rect, option.palette,StarRating::ReadOnly);} else {QStyledItemDelegate::paint(painter, option, index);}}

每一個item都會調(diào)用這個函數(shù),通過使用model中的QModelIndex對象來表示(估計是可以表示到哪一行調(diào)用了這個函數(shù)),如果存儲的數(shù)據(jù)類型就是那一坨星星,那就讓他進行繪制(源碼中可以看到一個if else,說的就是這個),否則使用QItemDelegate進行繪制。這樣就確保了StarDelegate更加的靈活。

當(dāng)item顯示的是一坨星星時,選中item時會搞一個背景,然后通過使用StarRating::paint()來畫item。

?

那一坨星星可以存到QVariant里面,這歸功于Q_DECLARE_METATYPE()這個宏。


用戶開始編輯一個Item的時候就會調(diào)用createEditor()

QWidget *StarDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const{if (index.data().canConvert<StarRating>()) {StarEditor *editor = new StarEditor(parent);connect(editor, &StarEditor::editingFinished,this, &StarDelegate::commitAndCloseEditor);return editor;} else {return QStyledItemDelegate::createEditor(parent, option, index);}}

如果item里面放了那一坨星星,重寫StartEditor這函數(shù)并且讓editingFinished()信號與commitAndCloseEidtor()型號連接起來,目的是當(dāng)關(guān)閉編輯功能后能更新模型。

關(guān)于commitAndCloseEdit()的代碼!

void StarDelegate::commitAndCloseEditor(){StarEditor *editor = qobject_cast<StarEditor *>(sender());emit commitData(editor);emit closeEditor(editor);}

當(dāng)用戶做完編輯時,就emit commitData()和closeEditor()(這兩個信號都來源于QAbstractItemDelegate),這個是為了通知模型正在編輯數(shù)據(jù)并且通知視圖不要讓他編輯。

setEditorData()函數(shù)當(dāng)要實現(xiàn)編輯功能的時候創(chuàng)建的,從模型中獲取數(shù)據(jù)并且初始化他!

void StarDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const{if (index.data().canConvert<StarRating>()) {StarRating starRating = qvariant_cast<StarRating>(index.data());StarEditor *starEditor = qobject_cast<StarEditor *>(editor);starEditor->setStarRating(starRating);} else {QStyledItemDelegate::setEditorData(editor, index);}}

此處源碼里面編輯的時候調(diào)用了setStarRating()這函數(shù)!


當(dāng)完成編輯的時候,就會調(diào)用setModelData()這個函數(shù),作用是把editor中的數(shù)據(jù)給模型:

void StarDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const{if (index.data().canConvert<StarRating>()) {StarEditor *starEditor = qobject_cast<StarEditor *>(editor);model->setData(index, QVariant::fromValue(starEditor->starRating()));} else {QStyledItemDelegate::setModelData(editor, model, index);}}

sizeHint()這個函數(shù)返回item的最合適的大小!

QSize StarDelegate::sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const{if (index.data().canConvert<StarRating>()) {StarRating starRating = qvariant_cast<StarRating>(index.data());return starRating.sizeHint();} else {return QStyledItemDelegate::sizeHint(option, index);}}

StarEditor Class Definition

StarDelegate類在實例化的時候要使用StarEditor,關(guān)于StartEditor代碼如下:

class StarEditor : public QWidget{Q_OBJECTpublic:StarEditor(QWidget *parent = 0);QSize sizeHint() const Q_DECL_OVERRIDE;void setStarRating(const StarRating &starRating) {myStarRating = starRating;}StarRating starRating() { return myStarRating; }signals:void editingFinished();protected:void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;private:int starAtPosition(int x);StarRating myStarRating;};

這個類通過移動鼠標(biāo)讓用戶編輯那一坨星星數(shù)據(jù),當(dāng)鼠標(biāo)單擊一個item后會emiteditingFinished()的信號。

這個類從繼承與QWidget,通過重寫這些函數(shù)來重新實現(xiàn)mouse和paint的事件。startAtPosition()這個函數(shù)是一個輔助函數(shù)返回鼠標(biāo)指向的星星的指針(就是指向那個坨星星的哪一個位置)

?

StarEditor Class Implementation

start的構(gòu)造函數(shù):

StarEditor::StarEditor(QWidget *parent): QWidget(parent){setMouseTracking(true);setAutoFillBackground(true);}

通過setMouseTracking這個函數(shù)去啟動鼠標(biāo)追蹤,即使用戶沒有點擊鼠標(biāo),也能監(jiān)聽到鼠標(biāo)。一般都開打QWidget自動填充的特性用于獲取不透明的背景(如果不調(diào)用,視圖的Editor就會干擾這個編輯器)

下面是關(guān)于paintEvent()函數(shù)

void StarEditor::paintEvent(QPaintEvent *){QPainter painter(this);myStarRating.paint(&painter, rect(), this->palette(),StarRating::Editable);}

通過這個函數(shù)去畫星星,這個函數(shù)就和StarDelegate差不多一毛一樣。

void StarEditor::mouseMoveEvent(QMouseEvent *event){int star = starAtPosition(event->x());if (star != myStarRating.starCount() && star != -1) {myStarRating.setStarCount(star);update();}}

在鼠標(biāo)事件里面調(diào)用setStartCount(),通過使用成員myStarRating得到當(dāng)前光標(biāo)的位置,并且調(diào)用QWidget::update()去讓他強制重繪。

void StarEditor::mouseReleaseEvent(QMouseEvent * /* event */){emit editingFinished();}

當(dāng)用戶釋放鼠標(biāo),就emit editingFinished()信號

int StarEditor::starAtPosition(int x){int star = (x / (myStarRating.sizeHint().width()/ myStarRating.maxStarCount())) + 1;if (star <= 0 || star > myStarRating.maxStarCount())return -1;return star;}

startAtPosition這個函數(shù)使用了基礎(chǔ)的線性代數(shù)去尋找當(dāng)前光標(biāo)對應(yīng)那一坨星星中哪個星星的位置。

?

StarRating Class Definition

class StarRating{public:enum EditMode { Editable, ReadOnly };explicit StarRating(int starCount = 1, int maxStarCount = 5);void paint(QPainter *painter, const QRect &rect,const QPalette &palette, EditMode mode) const;QSize sizeHint() const;int starCount() const { return myStarCount; }int maxStarCount() const { return myMaxStarCount; }void setStarCount(int starCount) { myStarCount = starCount; }void setMaxStarCount(int maxStarCount) { myMaxStarCount = maxStarCount; }private:QPolygonF starPolygon;QPolygonF diamondPolygon;int myStarCount;int myMaxStarCount;};Q_DECLARE_METATYPE(StarRating)

StarRating類代表了星星的等級(就是那一坨星星有幾個組成),不僅如此他還提供了畫那一坨星星的能力,這個是通過QPaintDevice實現(xiàn)的,這個一坨星星可以在view上畫,或者在編輯器上畫。myStarCount這個成員存儲了當(dāng)前有幾個星星,myMaxStarCount存儲了最多有多少個星星(存在QVariant這個神器里面)
?

通過Q_DECLARE_METATYPE()這個宏人QVariant知曉StarPating這個類,讓QVariant能存儲StarPating這個類。
?

StarRating Class Implementation

構(gòu)造函數(shù)初始化了myStarCount和myMaxStarCount并且構(gòu)造了一個多邊形(就是星星)和鉆石(非星星用這個代替)

StarRating::StarRating(int starCount, int maxStarCount){myStarCount = starCount;myMaxStarCount = maxStarCount;starPolygon << QPointF(1.0, 0.5);for (int i = 1; i < 5; ++i)starPolygon << QPointF(0.5 + 0.5 * std::cos(0.8 * i * 3.14),0.5 + 0.5 * std::sin(0.8 * i * 3.14));diamondPolygon << QPointF(0.4, 0.5) << QPointF(0.5, 0.4)<< QPointF(0.6, 0.5) << QPointF(0.5, 0.6)<< QPointF(0.4, 0.5);}

paint()函數(shù)在StarRating這個對象的paint device上畫了星星。

void StarRating::paint(QPainter *painter, const QRect &rect,const QPalette &palette, EditMode mode) const{painter->save();painter->setRenderHint(QPainter::Antialiasing, true);painter->setPen(Qt::NoPen);if (mode == Editable) {painter->setBrush(palette.highlight());} else {painter->setBrush(palette.foreground());}int yOffset = (rect.height() - PaintingScaleFactor) / 2;painter->translate(rect.x(), rect.y() + yOffset);painter->scale(PaintingScaleFactor, PaintingScaleFactor);for (int i = 0; i < myMaxStarCount; ++i) {if (i < myStarCount) {painter->drawPolygon(starPolygon, Qt::WindingFill);} else if (mode == Editable) {painter->drawPolygon(diamondPolygon, Qt::WindingFill);}painter->translate(1.0, 0.0);}painter->restore();}

首先設(shè)置了一個畫筆(pen)和畫刷(brush這兩個以后都用英文表示把,用中文太難過了)去畫圖。mode這個參數(shù)可以被設(shè)置成可編輯的或者可讀的,如果是可編輯的就要用Highligh color去代替Foreground color,從而才能更好的畫那一坨星星。

在編輯的時候,通過光標(biāo)控制星星,沒有星星的地方用小方塊代替。

sizeHint()函數(shù)返回畫出來的這坨星星最適合的大小:

QSize StarRating::sizeHint() const{return PaintingScaleFactor * QSize(myMaxStarCount, 1);}

最大也只能畫出myMaxStarCount這么多的星星。這個函數(shù)會被StarDelegate::sizeHint()與StartEditor::sizeHint()調(diào)用。

?

The main() Function

代碼如下:

int main(int argc, char *argv[]){QApplication app(argc, argv);QTableWidget tableWidget(4, 4);tableWidget.setItemDelegate(new StarDelegate);tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked| QAbstractItemView::SelectedClicked);tableWidget.setSelectionBehavior(QAbstractItemView::SelectRows);QStringList headerLabels;headerLabels << "Title" << "Genre" << "Artist" << "Rating";tableWidget.setHorizontalHeaderLabels(headerLabels);populateTableWidget(&tableWidget);tableWidget.resizeColumnsToContents();tableWidget.resize(500, 300);tableWidget.show();return app.exec();}

主函數(shù)創(chuàng)建了一個QTableWidget和設(shè)置了StartDelegate,DoubleClicked和SelectedClicked已經(jīng)設(shè)置好了編輯觸發(fā)的功能,當(dāng)星星等級的item被單擊選中后,就會打開編輯功能。
?

populateTableWidget()這個函數(shù)填充了QTableWidget的數(shù)據(jù)
?

void populateTableWidget(QTableWidget *tableWidget){static const struct {const char *title;const char *genre;const char *artist;int rating;} staticData[] = {{ "Mass in B-Minor", "Baroque", "J.S. Bach", 5 },...{ 0, 0, 0, 0 }};for (int row = 0; staticData[row].title != 0; ++row) {QTableWidgetItem *item0 = new QTableWidgetItem(staticData[row].title);QTableWidgetItem *item1 = new QTableWidgetItem(staticData[row].genre);QTableWidgetItem *item2 = new QTableWidgetItem(staticData[row].artist);QTableWidgetItem *item3 = new QTableWidgetItem;item3->setData(0,QVariant::fromValue(StarRating(staticData[row].rating)));tableWidget->setItem(row, 0, item0);tableWidget->setItem(row, 1, item1);tableWidget->setItem(row, 2, item2);tableWidget->setItem(row, 3, item3);}}

注意:使用qVariantFromValue把StarRating轉(zhuǎn)化為QVariant

?

Possible Extensions and Suggestions

在Qt的視圖模型框架里面有很多自定義方法,這個例子適合大多數(shù)自定義委托和編輯(我估計在國內(nèi)18k內(nèi)的Qt開發(fā)足夠用了,18k外的可能要用別的),這個例子的星星委托和編輯沒有盡可能做到以下幾點:
1.使用編輯的方式,這種方式要調(diào)用QAbstractItemView::edit(),用這個代替編輯觸發(fā)。這可以支持其他編譯器的觸發(fā),比如QAbstractItemView::EditTrigger。舉個例子,通過鼠標(biāo)懸移動來改變數(shù)據(jù)這種效果比點擊更好。
2.通過重寫QAbstractItemDelegate::editorEvent(),這可以直接實現(xiàn)委托的編輯,而不是創(chuàng)建一個QWidget的子類來實現(xiàn)!
?

總結(jié)

以上是生活随笔為你收集整理的Qt官方文档阅读笔记-对官方Star Delegate Example实例的解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。