翻譯|使用教程|編輯:龔雪|2023-02-16 10:35:38.067|閱讀 190 次
概述:本教程將為大家介紹每個UI開發人員都應該了解的ModelView編程,歡迎下載相關組件體驗~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
每個UI開發人員都應該了解ModelView編程,本教程的目標是為大家提供一個簡單易懂的介紹。
Qt 是目前最先進、最完整的跨平臺C++開發工具。它不僅完全實現了一次編寫,所有平臺無差別運行,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用于超過70個行業、數千家企業,支持數百萬設備及應用。
在上文中,我們主要為大家介紹了Model/View(模型/視圖)的一些基本概念(點擊這里回顧>>),本文將繼續為大家介紹如何創建一個簡單的模型/視圖應用。
Qt技術交流群:166830288 歡迎一起進群討論
如果想開發一個模型/視圖應用程序,應該從哪里開始呢?我們建議從一個簡單的示例開始,逐步擴展它,這使得理解體系結構更加容易。對于許多開發人員來說,在調用IDE之前試圖詳細理解模型/視圖體系結構是不太方便的,從具有演示數據的簡單模型/視圖應用程序開始實際上更容易。
下面是7個非常簡單且獨立的應用程序,它們展示了模型/視圖編程的不同方面,源代碼可以在examples/widgets/tutorials/modelview目錄中找到。
我們仍然有一個只讀表,但這一次內容每秒都在變化,因為正在顯示當前時間。
(文件來源: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(); }
時鐘的滴答聲缺少了一些東西,需要每一秒都告訴視圖時間已經改變、需要再次讀取。我們用定時器來做這個,在構造函數中,我們將其間隔設置為1秒,并連接其超時信號。
(文件來源: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(); }
這里是對應的槽位:
(文件來源: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}); }
通過發出() 信號,我們要求視圖再次讀取左上角單元格中的數據。注意,沒有顯式地將dataChanged()信號連接到視圖,這在調用setModel()時自動發生。
標題可以通過一個視圖方法隱藏:ableView->verticalHeader()->hide();
然而,頭部內容是通過模型設置的,所以我們重新實現headerData()方法:
(文件來源: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(); }
注意,方法()也有一個參數role,其含義與()中的相同。
在本例中,我們將構建一個應用程序,通過重復輸入到表格單元格中的值,自動用內容填充窗口標題。為了能夠方便地訪問窗口標題,我們將放在中。
模型決定編輯功能是否可用,為了啟用可用的編輯功能,我們只需要修改模型,這是通過重新實現以下虛擬方法來實現的:() 和()。
(文件來源: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 &); };
我們使用二維數組QString m_gridData來存儲數據,這使得m_gridData成為MyModel的核心。MyModel的其余部分就像一個包裝器,并將m_gridData適配到QAbstractItemModel接口,同時我們引入了editCompleted()信號,這使得將修改后的文本傳輸到窗口標題成為可能。
(文件來源: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; }
每次用戶編輯單元格時都會調用(),index參數告訴我們編輯了哪個字段,value提供了編輯過程的結果。角色總是被設置為 ,因為我們的單元格只包含文本,如果存在一個復選框,并且用戶權限設置為允許選擇該復選框,則調用也會將角色設置為。
(文件來源:examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
Qt::ItemFlags MyModel::flags(const QModelIndex &index) const { return Qt::ItemIsEditable | QAbstractTableModel::flags(index); }
可以使用()調整單元格的各種屬性。
返回足以向編輯器顯示一個單元格可以被選擇。
如果編輯一個單元格修改的數據多于該特定單元格中的數據,則模型必須發出()信號,以便讀取已更改的數據。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網