Qt中MVD模式的具體使用
一、前言
MVD 模式的核心價值:關注點分離,讓數(shù)據(jù)管理、顯示邏輯和用戶交互各自獨立,從而創(chuàng)建出更可維護、可擴展的應用程序。
Model: 完全不知道數(shù)據(jù)會如何顯示,只負責存儲和管理數(shù)據(jù)。
View :視圖作為橋梁,從 Model 獲取數(shù)據(jù)、將數(shù)據(jù)傳遞給 Delegate 進行渲染、處理用戶交互事件
Delegate :委托完全控制每個項目的外觀,包括顏色、布局、邊框等。
好處:
修改方便:
- 可以輕松更換不同的 Model 來改變數(shù)據(jù)源
- 可以輕松更換不同的 View 來改變交互方式
- 可以輕松更換不同的 Delegate 來改變外觀
松耦合設計
- 修改數(shù)據(jù)不影響顯示邏輯
- 修改顯示樣式不影響數(shù)據(jù)
- 各部分可以獨立開發(fā)和測試
二、Model
基礎模型類型:
QStringListModel - 字符串列表模型
#include <QStringListModel>
QStringListModel *model = new QStringListModel;
model->setStringList({"蘋果", "香蕉", "橙子"});QStandardItemModel - 標準項目模型
#include <QStandardItemModel>
QStandardItemModel *model = new QStandardItemModel;
model->appendRow(new QStandardItem("項目1"));QFileSystemModel - 文件系統(tǒng)模型
#include <QFileSystemModel> QFileSystemModel *model = new QFileSystemModel; model->setRootPath(QDir::homePath());
三、View
- QListView:將數(shù)據(jù)項顯示為列表。
- QTableView:將數(shù)據(jù)項顯示在表格中。
- QTreeView:將數(shù)據(jù)項顯示在層次結構的樹中。
- QColumnView:使用多個列顯示數(shù)據(jù)項,每個列代表一個層次級別。
- QHeaderView:用于顯示表格或列表的標題行或標題列,通常不單獨使用,而是作為QTableView和QTreeView的一部分。
- QListWidget、QTableWidget、QTreeWidget:這些是方便類,內部已經集成了模型,適用于簡單應用。但它們不符合嚴格的MVC模式,因為模型和視圖是捆綁在一起的。
四、delegate
常用的委托方式:
- 使用內置委托:QT提供了一些內置的委托類,如
QStyledItemDelegate和QItemDelegate。通常推薦使用QStyledItemDelegate,因為它使用當前樣式來繪制項目。 內置委托: - QT的內置委托可以處理大多數(shù)常見的數(shù)據(jù)類型(如字符串、數(shù)字、日期等)的顯示和編輯。例如,當你在一個模型/視圖結構中編輯一個布爾值時,內置委托會提供一個復選框;編輯數(shù)字時,會提供一個數(shù)字輸入框等。
- 自定義委托:通過繼承
QStyledItemDelegate或QItemDelegate,并重寫其虛函數(shù)來實現(xiàn)自定義的顯示和編輯行為。 - 自定義委托:自定義委托通常需要重寫以下一個或多個函數(shù):
paint(): 用于自定義項目的顯示。sizeHint(): 返回項目的大小。createEditor(): 返回一個用于編輯項目的部件(如QLineEdit、QComboBox等)。setEditorData(): 將模型中的數(shù)據(jù)設置到編輯器。setModelData(): 將編輯器中的數(shù)據(jù)保存到模型。updateEditorGeometry(): 設置編輯器在視圖中的位置和大小。
五、案例
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QListView>
#include <QStringListModel>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
// 前向聲明
class QListView;
class QStringListModel;
class SimpleDelegate;
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private:
void setupUI();
void setupModel();
QListView *listView;
QStringListModel *model;
SimpleDelegate *delegate;
};
#endif // MAINWINDOW_H.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QListView>
#include <QStringListModel>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
class SimpleDelegate : public QStyledItemDelegate
{
public:
explicit SimpleDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
// 繪制背景
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, QColor(173, 216, 230)); // 淺藍色選中背景
} else {
painter->fillRect(option.rect, Qt::white); // 白色默認背景
}
// 繪制文本
QString text = index.data(Qt::DisplayRole).toString();
painter->setPen(Qt::black);
painter->drawText(option.rect, Qt::AlignCenter, text);
// 繪制邊框
painter->setPen(Qt::lightGray);
painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
// 設置項目大小
QSize size = QStyledItemDelegate::sizeHint(option, index);
size.setHeight(40); // 固定高度
return size;
}
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, listView(new QListView(this))
, model(new QStringListModel(this))
, delegate(new SimpleDelegate(this))
{
ui->setupUi(this);
setupUI();
setupModel();
setWindowTitle("QT6 MVD 簡單示例");
resize(300, 300);
}
void MainWindow::setupUI()
{
// 創(chuàng)建中央部件
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// 設置列表視圖屬性
listView->setModel(model);
listView->setItemDelegate(delegate);
listView->setAlternatingRowColors(true); // 交替行顏色
// 創(chuàng)建布局
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(listView);
}
void MainWindow::setupModel()
{
// 創(chuàng)建示例數(shù)據(jù)
QStringList data;
data << "任務1: 學習 QT6"
<< "任務2: 理解 MVD 模式"
<< "任務3: 編寫示例代碼"
<< "任務4: 測試應用程序"
<< "任務5: 優(yōu)化界面效果";
// 設置模型數(shù)據(jù)
model->setStringList(data);
}
MainWindow::~MainWindow()
{
delete ui;
}結果:

功能演示:
我可一只修改delegate中的 painter->fillRect(option.rect, Qt::white); // 白色默認背景將背景變?yōu)閞ed;

到此這篇關于Qt中MVD模式的具體使用的文章就介紹到這了,更多相關Qt MVD模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++實現(xiàn)LeetCode(137.單獨的數(shù)字之二)
這篇文章主要介紹了C++實現(xiàn)LeetCode(137.單獨的數(shù)字之二),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-07-07

