翻譯|使用教程|編輯:龔雪|2023-02-16 10:35:38.067|閱讀 190 次
概述:本教程將為大家介紹每個(gè)UI開(kāi)發(fā)人員都應(yīng)該了解的ModelView編程,歡迎下載相關(guān)組件體驗(yàn)~
# 界面/圖表報(bào)表/文檔/IDE等千款熱門(mén)軟控件火熱銷(xiāo)售中 >>
相關(guān)鏈接:
每個(gè)UI開(kāi)發(fā)人員都應(yīng)該了解ModelView編程,本教程的目標(biāo)是為大家提供一個(gè)簡(jiǎn)單易懂的介紹。
Qt 是目前最先進(jìn)、最完整的跨平臺(tái)C++開(kāi)發(fā)工具。它不僅完全實(shí)現(xiàn)了一次編寫(xiě),所有平臺(tái)無(wú)差別運(yùn)行,更提供了幾乎所有開(kāi)發(fā)過(guò)程中需要用到的工具。如今,Qt已被運(yùn)用于超過(guò)70個(gè)行業(yè)、數(shù)千家企業(yè),支持?jǐn)?shù)百萬(wàn)設(shè)備及應(yīng)用。
在上文中,我們主要為大家介紹了Model/View(模型/視圖)的一些基本概念(點(diǎn)擊這里回顧>>),本文將繼續(xù)為大家介紹如何創(chuàng)建一個(gè)簡(jiǎn)單的模型/視圖應(yīng)用。
Qt技術(shù)交流群:166830288 歡迎一起進(jìn)群討論
如果想開(kāi)發(fā)一個(gè)模型/視圖應(yīng)用程序,應(yīng)該從哪里開(kāi)始呢?我們建議從一個(gè)簡(jiǎn)單的示例開(kāi)始,逐步擴(kuò)展它,這使得理解體系結(jié)構(gòu)更加容易。對(duì)于許多開(kāi)發(fā)人員來(lái)說(shuō),在調(diào)用IDE之前試圖詳細(xì)理解模型/視圖體系結(jié)構(gòu)是不太方便的,從具有演示數(shù)據(jù)的簡(jiǎn)單模型/視圖應(yīng)用程序開(kāi)始實(shí)際上更容易。
下面是7個(gè)非常簡(jiǎn)單且獨(dú)立的應(yīng)用程序,它們展示了模型/視圖編程的不同方面,源代碼可以在examples/widgets/tutorials/modelview目錄中找到。
我們?nèi)匀挥幸粋€(gè)只讀表,但這一次內(nèi)容每秒都在變化,因?yàn)檎陲@示當(dāng)前時(shí)間。
(文件來(lái)源:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
QVariant MyModel::data(const QModelIndex &index, int role) const { int row = index.row(); int col = index.column(); if (role == Qt::DisplayRole && row == 0 && col == 0) return QTime::currentTime().toString(); return QVariant(); }
時(shí)鐘的滴答聲缺少了一些東西,需要每一秒都告訴視圖時(shí)間已經(jīng)改變、需要再次讀取。我們用定時(shí)器來(lái)做這個(gè),在構(gòu)造函數(shù)中,我們將其間隔設(shè)置為1秒,并連接其超時(shí)信號(hào)。
(文件來(lái)源:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent) , timer(new QTimer(this)) { timer->setInterval(1000); connect(timer, &QTimer::timeout , this, &MyModel::timerHit); timer->start(); }
這里是對(duì)應(yīng)的槽位:
(文件來(lái)源:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
void MyModel::timerHit() { // we identify the top left cell QModelIndex topLeft = createIndex(0,0); // emit a signal to make the view reread identified data emit dataChanged(topLeft, topLeft, {Qt::DisplayRole}); }
通過(guò)發(fā)出() 信號(hào),我們要求視圖再次讀取左上角單元格中的數(shù)據(jù)。注意,沒(méi)有顯式地將dataChanged()信號(hào)連接到視圖,這在調(diào)用setModel()時(shí)自動(dòng)發(fā)生。
標(biāo)題可以通過(guò)一個(gè)視圖方法隱藏:ableView->verticalHeader()->hide();
然而,頭部?jī)?nèi)容是通過(guò)模型設(shè)置的,所以我們重新實(shí)現(xiàn)headerData()方法:
(文件來(lái)源:examples/widgets/tutorials/modelview/4_headers/mymodel.cpp)
QVariant MyModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case 0: return QString("first"); case 1: return QString("second"); case 2: return QString("third"); } } return QVariant(); }
注意,方法()也有一個(gè)參數(shù)role,其含義與()中的相同。
在本例中,我們將構(gòu)建一個(gè)應(yīng)用程序,通過(guò)重復(fù)輸入到表格單元格中的值,自動(dòng)用內(nèi)容填充窗口標(biāo)題。為了能夠方便地訪問(wèn)窗口標(biāo)題,我們將放在中。
模型決定編輯功能是否可用,為了啟用可用的編輯功能,我們只需要修改模型,這是通過(guò)重新實(shí)現(xiàn)以下虛擬方法來(lái)實(shí)現(xiàn)的:() 和()。
(文件來(lái)源:examples/widgets/tutorials/modelview/5_edit/mymodel.h)
// mymodel.h #include <QAbstractTableModel> #include <QString> const int COLS= 3; const int ROWS= 2; class MyModel : public QAbstractTableModel { Q_OBJECT public: MyModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; private: QString m_gridData[ROWS][COLS]; //holds text entered into QTableView signals: void editCompleted(const QString &); };
我們使用二維數(shù)組QString m_gridData來(lái)存儲(chǔ)數(shù)據(jù),這使得m_gridData成為MyModel的核心。MyModel的其余部分就像一個(gè)包裝器,并將m_gridData適配到QAbstractItemModel接口,同時(shí)我們引入了editCompleted()信號(hào),這使得將修改后的文本傳輸?shù)酱翱跇?biāo)題成為可能。
(文件來(lái)源:examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role == Qt::EditRole) { if (!checkIndex(index)) return false; //save value from editor to member m_gridData m_gridData[index.row()][index.column()] = value.toString(); //for presentation purposes only: build and emit a joined string QString result; for (int row = 0; row < ROWS; row++) { for (int col= 0; col < COLS; col++) result += m_gridData[row][col] + ' '; } emit editCompleted(result); return true; } return false; }
每次用戶(hù)編輯單元格時(shí)都會(huì)調(diào)用(),index參數(shù)告訴我們編輯了哪個(gè)字段,value提供了編輯過(guò)程的結(jié)果。角色總是被設(shè)置為 ,因?yàn)槲覀兊膯卧裰话谋荆绻嬖谝粋€(gè)復(fù)選框,并且用戶(hù)權(quán)限設(shè)置為允許選擇該復(fù)選框,則調(diào)用也會(huì)將角色設(shè)置為。
(文件來(lái)源:examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
Qt::ItemFlags MyModel::flags(const QModelIndex &index) const { return Qt::ItemIsEditable | QAbstractTableModel::flags(index); }
可以使用()調(diào)整單元格的各種屬性。
返回足以向編輯器顯示一個(gè)單元格可以被選擇。
如果編輯一個(gè)單元格修改的數(shù)據(jù)多于該特定單元格中的數(shù)據(jù),則模型必須發(fā)出()信號(hào),以便讀取已更改的數(shù)據(jù)。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:慧都網(wǎng)