前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt / Model_View_Delegate

Qt / Model_View_Delegate

作者头像
Kano365
修改2022-04-12 18:25:13
1.6K0
修改2022-04-12 18:25:13
举报
文章被收录于专栏:YYYQQQZZZYYYQQQZZZ

定义

早期Qt:传统的窗口部件,其本身内部包含,用于存储数据的内置容器。(直观,但是同步数据较低效)

当前Qt:模型 / 视图,model / View,窗口部件如Widget无需维护内部的数据容器,其通过标准的接口获得外部数据。(更高效,避免数据重复)

模型/视图编程的典型代表:Smalltalk语言设计的,大数据集可视化方法—模型—视图—控制器(Model-View-Controller,MVC)。

  • Model(模型):处理数据的逻辑部分,通常负责在数据库中存取数据
  • View(视图):用于数据的显示部分,通常视图的依靠模型的数据而创建的。
  • Controller(控制器):处理用户的交互问题。负责从View读取数据,控制用户的输入,并间接向Model发送数据。

Qt中的应用

Qt的Model /View可以理解是对MVC的变形,将控制器替换成了稍微有些不同的抽象:委托(delegate)。Qt对每种类型的视图都提供了默认的委托,这对绝大多数应用程序而言已经足够了,所以通常我们不需要注意它。

Qt:Model—View—Delegate

对于Qt的Model /View我们可以简单的划分为3种使用级别:

①Model /View的简便类:如QListWidget、QTableWidget、QTreeWidget

②Model /View的预定义模型:如QStringListModel、QStanderItemModel、QFileSystemMode等模型以及数据库模型

③Model /View的自定义模型。可以自定义委托

Ⅰ QTableWidget(不区分模型 / 视图)——已封装好,固定

QTableWidget中每一个项都使用一个QTableWidgetItem表示,tableWidget->item()->setText()则用来设置QTableWidgetItem的内容。

代码语言:javascript
复制
CoordinateSetter::CoordinateSetter(QList<QPointF> *coords,
                                   QWidget *parent)
    : QDialog(parent)
{
    coordinates = coords;

    tableWidget = new QTableWidget(0, 2);
    tableWidget->setHorizontalHeaderLabels(
            QStringList() << tr("X") << tr("Y"));

    for (int row = 0; row < coordinates->count(); ++row) {
        QPointF point = coordinates->at(row);
        slot_addRow();
        tableWidget->item(row, 0)->setText(QString::number(point.x()));
        tableWidget->item(row, 1)->setText(QString::number(point.y()));
    }
    setWindowTitle(tr("Coordinate Setter"));
}

QTableWidget::insertRow()插入一个新行,使用QTableWidgetItem 创建两个Item,之后使用QTableWidget::setItem()将他们添加到列表中。

代码语言:javascript
复制
void CoordinateSetter::slot_addRow()
{
    int row = tableWidget->rowCount();
    tableWidget->insertRow(row);

    QTableWidgetItem *item0 = new QTableWidgetItem;
    item0->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
    tableWidget->setItem(row, 0, item0);

    QTableWidgetItem *item1 = new QTableWidgetItem;
    item1->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
    tableWidget->setItem(row, 1, item1);

    tableWidget->setCurrentItem(item0);
}

最后,用户点击Ok按钮时,则会清空传递给这个对话框的人坐标,并且根据这个QTableWidget的所有Item创建一个新的坐标集。运行结果如下:

添加描述

Ⅱ Model(QDirModel / QFileSystemModel)结合View(ListView TableView)

Model不关心数据源,数据源可以是数据库或是其他形式,根据数据的特点选择合适的Model,最后再根据要展现给用户的形式选取一个View。按照上述的结构,也就达到了UI、业务逻辑和数据分离的效果了。

代码语言:javascript
复制
//create Model
mp_fileSystemModel = new QFileSystemModel;
mp_fileSystemModel->setRootPath(QDir::currentPath());、

//tableView add the model
void Widget::on_pbn_tableView_clicked()
{
    ui->tableView->setModel(mp_fileSystemModel);
    ui->tableView->setRootIndex(mp_fileSystemModel->index(QDir::currentPath()));
}

ListView

添加描述

TableView

添加描述

QTreeView

代码语言:javascript
复制
    //create and set Model
    mp_dirModel = new QDirModel;
    //可编辑
    mp_dirModel->setReadOnly(false);
    //初始排序属性
    mp_dirModel->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);
    
    //create View and bind 
    mp_treeView = new QTreeView(this);
    mp_treeView->setModel(mp_dirModel);
    mp_treeView->setRootIndex(mp_dirModel->index(QDir::currentPath()));
    mp_treeView->header()->setStretchLastSection(true);
    mp_treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
    mp_treeView->header()->setSortIndicatorShown(true);
    mp_treeView->header()->setSectionsClickable(true);
    //设置treeView的模型以及treeView的View属性。

void treeView::slot_createDirectory()
{
    QModelIndex index = mp_treeView->currentIndex();
    if (!index.isValid())
        return;

    QString dirName = QInputDialog::getText(this,
                              tr("Create Directory"),
                              tr("Directory name"));
    if (!dirName.isEmpty()) {
        if (!mp_dirModel->mkdir(index, dirName).isValid())
            QMessageBox::information(this, tr("Create Directory"),
                    tr("Failed to create the directory"));
    }
}

添加描述

Ⅲ 自定义委托

像Qt里的事件一样,我们都是继承一个已经实现好了类,之后根据需要再实现自己的操作。

这里我想要实现的是双击单元格时,通过combox进行选择。QTableWidget没有这样功能,所以需要通过委托来实现,再所以就需要继承QItemDelegate,之后重新实现一些函数,和Qt 重新封装的OpenGL又有些类似。继承QItemDelegate,我们可以使用一些默认的功能,如果继承QAbstractItemDelegate,那就要从头开始实现更多的东西了。

1.自定义委托

代码语言:javascript
复制
//create ComboBoxDelegate #public QItemDelegate
class ComboBoxDelegate : public QItemDelegate
{
public:
    ComboBoxDelegate();

public:
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

//Use QComboBox to achieve corresponding function
QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //Use class QComboBox, proxy use through QItemDelegate
    QComboBox *editor = new QComboBox(parent);
    if(index.column() == 2){
            editor->addItem(QString::fromLocal8Bit("17"));
            editor->addItem(QString::fromLocal8Bit("18"));
            editor->setCurrentIndex(0);
            return editor;
     } else {
            return QItemDelegate::createEditor(parent,option,index);
    }
}

2.使用自定义委托

代码语言:javascript
复制
ui->tableWidget->setItemDelegateForColumn(2,new ComboBoxDelegate);

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义
  • Qt中的应用
    • Ⅰ QTableWidget(不区分模型 / 视图)——已封装好,固定
      • Ⅱ Model(QDirModel / QFileSystemModel)结合View(ListView TableView)
        • Ⅲ 自定义委托
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档