翻譯|使用教程|編輯:龔雪|2023-02-03 10:34:52.360|閱讀 184 次
概述:本教程將為大家介紹每個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@ke049m.cn
文章轉載自:慧都網