QT系列第7节 Model和View简介

       数据组织和数据展示是ui编程避不开的两个方面,QT中对数据组织(Model)和展示(View)都有完善的类支持。

     Model/View框架的核心思想是模型(数据)与视图(显示)相分离,模型对外提供标准接口存取数据,不关心数据如何显示,视图自定义数据的显示方式,不关心数据如何组织存储,即数据存储和渲染隔离开。

    Model/View框架中数据与显示的分离,可以允许使用不同界面显示同一数据,也能够在不改变数据的情况下添加新的显示界面。为了处理用户输入,引入了委托(delegate)。引入委托的好处是可以自定义数据项的渲染和编辑。

目录

1.Model / View结构介绍

2.数据模型

 3.视图

 4.代理

 5.使用举例

1.Model / View结构介绍

模型必须为每一个数据提供独一无二的索引,视图通过索引访问模型中的数据。

模型与数据源进行交互,为框架中其它组件提供接口。交互的本质在于数据源的类型以及模型的实现方式。视图从模型获取模型索引,通过将模型索引反向传给模型,视图又可以从数据源获取数据。在标准视图中,委托渲染数据项;在需要编辑数据时,委托使用直接模型索引直接与模型进行交互。

Model/View架构分为三部分:模型、视图和委托。每一个组件都由一个抽象类定义,抽象类提供了基本的公共接口以及一些默认实现。

模型、视图和委托使用信号槽进行交互:

 (1)底层维护的数据发生改变时,模型发出信号通知视图

 (2)当用户与视图进行交互时,视图发出信号提供了有关用户与界面进行交互的信息

 (3) 当用户编辑数据项时,委托发出信号用于告知模型和视图编辑器的状态。

2.数据模型

 3.视图

 4.代理

 5.使用举例

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileSystemModel>
#include "qintdelegate.h"

// Data直接到View
// Data => View

// Data通过通道Model到View
// Data => Model => View

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QFileSystemModel *m_fileModel;
    QIntDelegate intDelegate;

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_treeView_clicked(const QModelIndex &index);

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

qintdelegate.h

#ifndef QINTDELEGATE_H
#define QINTDELEGATE_H

#include <QObject>
#include <QStyledItemDelegate>

// 自定义代理
class QIntDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit QIntDelegate(QObject *parent = nullptr);
    //创建用于编辑数据的widget组件,如QSpinBox,QComboBox ...
    virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index);
    //从数据模型获取数据,供widget组件进行编辑
    virtual void setEditorData(QWidget *editor, const QModelIndex &index);
    //将widget上的数据更新到模型
    virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index);
    //用于给widget组件设置一个合适的大小
    virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index);

signals:

};

#endif // QINTDELEGATE_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDir>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_fileModel = new QFileSystemModel(this);
    m_fileModel->setRootPath(QDir::currentPath());
    ui->treeView->setModel(m_fileModel);
    ui->listView->setModel(m_fileModel);
    ui->tableView->setModel(m_fileModel);
    ui->tableView->verticalHeader()->setVisible(false);

    //信号和槽实现联动
    connect(ui->treeView, SIGNAL(clicked(QModelIndex)),
            ui->listView, SLOT(setRootIndex(QModelIndex)));
    connect(ui->treeView, SIGNAL(clicked(QModelIndex)),
            ui->tableView, SLOT(setRootIndex(QModelIndex)));

    ui->tableView->setItemDelegateForColumn(0, &intDelegate);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_treeView_clicked(const QModelIndex &index)
{
    ui->label->setText(m_fileModel->fileName(index));
    ui->label_4->setText(m_fileModel->filePath(index));
    ui->label_3->setText(m_fileModel->type(index));
    unsigned sz = m_fileModel->size(index)/1024;
    if (sz < 1024) {
        ui->label_2->setText(QString::asprintf("%d KB", sz));
    }
    else {
        ui->label_2->setText(QString::asprintf("%d MB", sz/1024));
    }
    ui->checkBox->setChecked(m_fileModel->isDir(index));
}

qintdelegate.cpp

#include "qintdelegate.h"
#include <QSpinBox>

QIntDelegate::QIntDelegate(QObject *parent)
    : QStyledItemDelegate{parent}
{

}

QWidget *QIntDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) {
    QSpinBox* editor = new QSpinBox(parent);
    editor->setMinimum(0);
    editor->setMaximum(1000);
    editor->setFrame(false);
    return editor;
}

void QIntDelegate::setEditorData(QWidget *editor, const QModelIndex &index) {
    int value = index.model()->data(index, Qt::EditRole).toInt();
    qDebug() << "value:: " << value;
    QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
    spinBox->setValue(value);
}

void QIntDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) {
    QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
    spinBox->interpretText();
    int value = spinBox->value();
    model->setData(index, value, Qt::EditRole);
}

void QIntDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) {
    editor->setGeometry(option.rect);
}

运行效果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值