翻譯|使用教程|編輯:龔雪|2023-02-24 10:17:22.760|閱讀 221 次
概述:本教程將為大家介紹每個(gè)UI開發(fā)人員都應(yīng)該了解的ModelView編程,歡迎下載相關(guān)組件體驗(yàn)~
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
每個(gè)UI開發(fā)人員都應(yīng)該了解ModelView編程,本教程的目標(biāo)是為大家提供一個(gè)簡單易懂的介紹。
Qt 是目前最先進(jìn)、最完整的跨平臺C++開發(fā)工具。它不僅完全實(shí)現(xiàn)了一次編寫,所有平臺無差別運(yùn)行,更提供了幾乎所有開發(fā)過程中需要用到的工具。如今,Qt已被運(yùn)用于超過70個(gè)行業(yè)、數(shù)千家企業(yè),支持?jǐn)?shù)百萬設(shè)備及應(yīng)用。
在上文中,我們主要為大家介紹了如何創(chuàng)建一個(gè)簡單的Model/View(模型/視圖)的應(yīng)用(點(diǎn)擊這里回顧>>),本文將繼續(xù)為大家介紹如何實(shí)現(xiàn)中間主題。
Qt技術(shù)交流群:166830288 歡迎一起進(jìn)群討論
開發(fā)人員可以將上面的示例轉(zhuǎn)換為具有樹視圖的應(yīng)用程序,簡單地將 替換為,這將產(chǎn)生一個(gè)讀/寫樹。不必對模型進(jìn)行任何更改,樹不會有任何層次結(jié)構(gòu),因?yàn)槟P捅旧頉]有任何層次結(jié)構(gòu)。
QListView、QTableView和QTreeView都使用一個(gè)模型抽象,它是一個(gè)合并的列表、表和樹,這使得從同一個(gè)模型中使用幾種不同類型的視圖類成為可能。
這是我們的示例模型到目前為止的樣子:
為了建立一個(gè)模型,我們把數(shù)據(jù)封裝在上面的示例中。這次使用QStandardItemModel,它是一個(gè)層次數(shù)據(jù)的容器,也實(shí)現(xiàn)了QAbstractItemModel。要顯示樹,QStandardItemModel必須用QStandardItems填充,QStandardItems能夠容納項(xiàng)目的所有標(biāo)準(zhǔn)屬性,如文本、字體、復(fù)選框或筆刷。
(文件來源:examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp)
// modelview.cpp #include "mainwindow.h" #include <QTreeView> #include <QStandardItemModel> #include <QStandardItem> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , treeView(new QTreeView(this)) , standardModel(new QStandardItemModel(this)) { setCentralWidget(treeView); QList<QStandardItem *> preparedRow = prepareRow("first", "second", "third"); QStandardItem *item = standardModel->invisibleRootItem(); // adding a row to the invisible root item produces a root element item->appendRow(preparedRow); QList<QStandardItem *> secondRow = prepareRow("111", "222", "333"); // adding a row to an item starts a subtree preparedRow.first()->appendRow(secondRow); treeView->setModel(standardModel); treeView->expandAll(); } QList<QStandardItem *> MainWindow::prepareRow(const QString &first, const QString &second, const QString &third) const { return {new QStandardItem(first), new QStandardItem(second), new QStandardItem(third)}; }
我們簡單地實(shí)例化一個(gè),并向構(gòu)造函數(shù)添加兩個(gè),然后可以創(chuàng)建一個(gè)層次數(shù)據(jù)結(jié)構(gòu),因?yàn)橐粋€(gè) 可以容納其他,節(jié)點(diǎn)在視圖中折疊和展開。
我們希望訪問選定項(xiàng)的內(nèi)容,以便將其與層次結(jié)構(gòu)級別一起輸出到窗口標(biāo)題中。
所以創(chuàng)建兩個(gè)項(xiàng)目:
(文件來源:examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
#include "mainwindow.h" #include <QTreeView> #include <QStandardItemModel> #include <QItemSelectionModel> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , treeView(new QTreeView(this)) , standardModel(new QStandardItemModel(this)) { setCentralWidget(treeView); auto *rootNode = standardModel->invisibleRootItem(); // defining a couple of items auto *americaItem = new QStandardItem("America"); auto *mexicoItem = new QStandardItem("Canada"); auto *usaItem = new QStandardItem("USA"); auto *bostonItem = new QStandardItem("Boston"); auto *europeItem = new QStandardItem("Europe"); auto *italyItem = new QStandardItem("Italy"); auto *romeItem = new QStandardItem("Rome"); auto *veronaItem = new QStandardItem("Verona"); // building up the hierarchy rootNode-> appendRow(americaItem); rootNode-> appendRow(europeItem); americaItem-> appendRow(mexicoItem); americaItem-> appendRow(usaItem); usaItem-> appendRow(bostonItem); europeItem-> appendRow(italyItem); italyItem-> appendRow(romeItem); italyItem-> appendRow(veronaItem); // register the model treeView->setModel(standardModel); treeView->expandAll(); // selection changes shall trigger a slot QItemSelectionModel *selectionModel = treeView->selectionModel(); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &MainWindow::selectionChangedSlot); }
視圖在單獨(dú)的選擇模型中管理選擇,可以使用() 方法檢索,檢索選擇模型是為了將一個(gè)槽連接到它的() 信號。
(文件來源:examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
void MainWindow::selectionChangedSlot(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/) { // get the text of the selected item const QModelIndex index = treeView->selectionModel()->currentIndex(); QString selectedText = index.data(Qt::DisplayRole).toString(); // find out the hierarchy level of the selected item int hierarchyLevel = 1; QModelIndex seekRoot = index; while (seekRoot.parent().isValid()) { seekRoot = seekRoot.parent(); hierarchyLevel++; } QString showString = QString("%1, Level %2").arg(selectedText) .arg(hierarchyLevel); setWindowTitle(showString); }
通過調(diào)用()來獲得與選擇相對應(yīng)的模型索引,并通過使用模型索引來獲得字段的字符串,然后只需計(jì)算該項(xiàng)的hierarchyLevel。頂級項(xiàng)沒有父項(xiàng),()方法將返回一個(gè)默認(rèn)構(gòu)造的,這就是為什么使用parent()方法迭代到頂層,同時(shí)計(jì)算迭代期間執(zhí)行的步驟。
選擇模型(如上所示)可以檢索,但也可以使用進(jìn)行設(shè)置。這就是為什么有3個(gè)視圖類具有同步選擇,因?yàn)橹皇褂昧诉x擇模型的一個(gè)實(shí)例。要在3個(gè)視圖之間共享選擇模型,請使用() 并使用setSelectionModel()將結(jié)果分配給第二個(gè)和第三個(gè)視圖類。
使用模型/視圖的典型方法是封裝特定的數(shù)據(jù),使其可用于視圖類。但是Qt也為公共底層數(shù)據(jù)結(jié)構(gòu)提供了預(yù)定義的模型,如果其中一種可用的數(shù)據(jù)結(jié)構(gòu)適合您的應(yīng)用程序,那么預(yù)定義模型可能是一個(gè)不錯(cuò)的選擇。
在迄今為止的所有示例中,數(shù)據(jù)在單元格中以文本或復(fù)選框的形式呈現(xiàn),并以文本或復(fù)選框的形式進(jìn)行編輯,提供這些表示和編輯服務(wù)的組件稱為delegate。一起來看一個(gè)名為Star Delegate的示例:
該視圖有一個(gè)setItemDelegate()方法,用于替換默認(rèn)delegate并安裝自定義delegate。一個(gè)新的delegate可以通過創(chuàng)建一個(gè)繼承自QStyledItemDelegate的類來編寫,為了編寫一個(gè)顯示星號且沒有輸入功能的delegate并安裝自定義delegate。一個(gè)新的delegate,我們只需要重寫2個(gè)方法。
class StarDelegate : public QStyledItemDelegate { Q_OBJECT public: StarDelegate(QWidget *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; };
paint()根據(jù)底層數(shù)據(jù)的內(nèi)容繪制星號,可以通過調(diào)用index.data()來查找數(shù)據(jù)。delegate的sizeHint()方法用于獲取每個(gè)星星的尺寸,因此單元格將提供足夠的高度和寬度來容納這些星星。
如果您想在視圖類的網(wǎng)格中使用自定義圖形表示方式顯示數(shù)據(jù),那么編寫自定義delegates是正確的選擇。如果想要離開網(wǎng)格,不會使用自定義delegates,可以使用自定義視圖類。
模型的被動特性為程序員提供了新的挑戰(zhàn),模型中的不一致可能導(dǎo)致應(yīng)用程序崩潰。由于模型受到來自視圖的大量調(diào)用的影響,因此很難找出哪個(gè)調(diào)用使應(yīng)用程序崩潰,以及哪個(gè)操作引入了問題。
Qt Labs提供了一種名為的軟件,可以在程序運(yùn)行時(shí)檢查模型。每當(dāng)模型被更改時(shí),ModelTest都會掃描模型并使用斷言報(bào)告錯(cuò)誤。這對于樹模型尤其重要,因?yàn)樗鼈兊膶哟涡再|(zhì)為微妙的不一致留下了許多可能性。
與視圖類不同,ModelTest使用超出范圍的索引來測試模型。這意味著您的應(yīng)用程序可能會在使用ModelTest時(shí)崩潰,即使沒有它它也可以完美地運(yùn)行。因此在使用ModelTest時(shí),您還需要處理所有超出范圍的索引。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:慧都網(wǎng)