翻譯|使用教程|編輯:龔雪|2023-02-03 10:34:52.360|閱讀 176 次
概述:本教程將為大家介紹每個UI開發人員都應該了解的ModelView編程,歡迎下載相關組件體驗~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
每個UI開發人員都應該了解ModelView編程,本教程的目標是為大家提供一個簡單易懂的介紹。
Qt 是目前最先進、最完整的跨平臺C++開發工具。它不僅完全實現了一次編寫,所有平臺無差別運行,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用于超過70個行業、數千家企業,支持數百萬設備及應用。
在上文中,我們主要為大家介紹了Model/View(模型/視圖)的一些基本概念(點擊這里回顧>>),本文將繼續為大家介紹如何創建一個簡單的模型/視圖應用。
Qt技術交流群:166830288 歡迎一起進群討論
如果想開發一個模型/視圖應用程序,應該從哪里開始呢?我們建議從一個簡單的示例開始,逐步擴展它,這使得理解體系結構更加容易。對于許多開發人員來說,在調用IDE之前試圖詳細理解模型/視圖體系結構是不太方便的,從具有演示數據的簡單模型/視圖應用程序開始實際上更容易。
下面是7個非常簡單且獨立的應用程序,它們展示了模型/視圖編程的不同方面,源代碼可以在examples/widgets/tutorials/modelview目錄中找到。
從一個使用顯示數據的應用程序開始,稍后我們將添加編輯功能。
(文件源:examples/widgets/tutorials/modelview/1_readonly/main.cpp)
// main.cpp #include <QApplication> #include <QTableView> #include "mymodel.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tableView; MyModel myModel; tableView.setModel(&myModel); tableView.show(); return a.exec(); }
我們有常用的main()函數:
我們創建了一個MyModel的實例,并使用將它的指針傳遞給,tableView將調用它接收到的指針的方法來找出兩件事:
模型需要一些代碼來響應這一點。
我們有一個表數據集,所以從開始,因為它比通用的更容易使用。
(文件源: examples/widgets/tutorials/modelview/1_readonly/mymodel.h)
// mymodel.h #include <QAbstractTableModel> class MyModel : public QAbstractTableModel { Q_OBJECT public: explicit 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; };
QAbstractTableModel需要實現三個抽象方法。
(文件源: examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp)
// mymodel.cpp #include "mymodel.h" MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent) { } int MyModel::rowCount(const QModelIndex & /*parent*/) const { return 2; } int MyModel::columnCount(const QModelIndex & /*parent*/) const { return 3; } QVariant MyModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return QString("Row%1, Column%2") .arg(index.row() + 1) .arg(index.column() +1); return QVariant(); }
行數和列數由()和()提供,當視圖必須知道單元格的文本是什么時,它調用()方法。行和列信息通過參數index指定,角色設置為,其他角色將在下一節中介紹。在我們的示例中,生成了應該顯示的數據,在實際應用程序中,MyModel有一個名為MyData的成員,它作為所有讀寫操作的目標。
這個小示例演示了模型的被動性質,模型不知道什么時候使用它,也不知道需要哪些數據,它只是在視圖每次請求時提供數據。
當模型的數據需要更改時會發生什么?視圖如何意識到數據已經改變,需要再次讀取?該模型必須發出一個信號,表明單元格的范圍發生了變化,這將在2.3節中演示。
除了控制視圖顯示的文本外,模型還控制文本的外觀,當我們稍微改變模型時,得到如下結果:
事實上,除了data()方法之外,沒有什么需要更改來設置字體、背景顏色、對齊方式和復選框。下面是data()方法,它產生如上所示的結果。不同之處在于,這次我們使用參數int role根據其值返回不同的信息。
(文件源: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp)
// mymodel.cpp QVariant MyModel::data(const QModelIndex &index, int role) const { int row = index.row(); int col = index.column(); // generate a log message when this method gets called qDebug() << QString("row %1, col%2, role %3") .arg(row).arg(col).arg(role); switch (role) { case Qt::DisplayRole: if (row == 0 && col == 1) return QString("<--left"); if (row == 1 && col == 1) return QString("right-->"); return QString("Row%1, Column%2") .arg(row + 1) .arg(col +1); case Qt::FontRole: if (row == 0 && col == 0) { // change font only for cell(0,0) QFont boldFont; boldFont.setBold(true); return boldFont; } break; case Qt::BackgroundRole: if (row == 1 && col == 2) // change background only for cell(1,2) return QBrush(Qt::red); break; case Qt::TextAlignmentRole: if (row == 1 && col == 1) // change text alignment only for cell(1,1) return int(Qt::AlignRight | Qt::AlignVCenter); break; case Qt::CheckStateRole: if (row == 1 && col == 0) // add a checkbox to cell(1,0) return Qt::Checked; break; } return QVariant(); }
每個格式化屬性將通過對data()方法的單獨調用從模型請求,role參數用于讓模型知道正在請求哪個屬性:
參考Qt命名空間文檔了解更多關于 enum功能的信息。
現在我們需要確定使用分離模型如何影響應用程序的性能,因此跟蹤視圖調用data()方法的頻率。為了跟蹤視圖調用模型的頻率,我們在data()方法中放入了一條調試語句,該語句將記錄到錯誤輸出流。在我們的小示例中,data()將被調用42次。每次將光標懸停在字段上時,data()將再次被調用——每個單元格調用7次。這就是為什么在調用data()和緩存昂貴的查找操作時,確保數據可用是很重要的。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網