Qt4的MVC模型视图小测试(2)

下面来尝试实现qabstractlistmodel的子类化。

首先新建c++类,继承在qabstractlistmodel类的stringlistmodel:

思路如下:

首先实现子类化的类,在类里实现列表的基本功能,再在widget构造函数里实现具体的控件功能,从而考察这个思路是否正确。只要改变string的值,是不是视图就自动跟着改变。

下面时子类化以后的编译通过界面:

这里放置了两个控件,一个是listview,一个是tableview,因为这里没有考虑层级关系,所以就不用treeview,只考虑这两个就可以。

先来实现一个头声明

#ifndef STRINGLISTMODEL_H
#define STRINGLISTMODEL_H

#include <QAbstractListModel>
#include <QStringList>

class StringListModel : public QAbstractListModel
{
    Q_OBJECT
public:
//    explicit StringListModel(QObject *parent = 0);
    StringListModel(const QStringList &strings, QObject *parent = 0)
        :QAbstractListModel(parent),stringList(strings){}

    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role) const;
    QVariant headerData(int Section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const;
signals:

public slots:


private:
    QStringList stringList;
};

#endif // STRINGLISTMODEL_H

 再来实现具体的cpp函数

#include "stringlistmodel.h"

//StringListModel::StringListModel(QObject *parent) :
//    QAbstractListModel(parent)
//{
//}


int StringListModel::rowCount(const QModelIndex &parent) const
{
    return stringList.count();
}

QVariant StringListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if(index.row()>=stringList.size())
        return QVariant();

    if(role==Qt::DisplayRole)
        return stringList.at(index.row());
    else
        return QVariant();
}


QVariant StringListModel::headerData(int Section, Qt::Orientation orientation,
                    int role) const
{
    if(role!=Qt::DisplayRole)
        return QVariant();

    if(orientation==Qt::Horizontal)
        return QString("Column %1").arg(Section);
    else
        return QString("Row %1").arg(Section);
}


















到这一步都是编译通过的,没问题。

下面开始在widget中实现:

#include "widget.h"
#include "ui_widget.h"

#include "stringlistmodel.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QStringList list;
    list<<"第1个项目: 孙悟空"<<"第2个项目: 沙师弟"<<"第3个项目: 刘畊宏";

    StringListModel *model = new StringListModel(list);

    ui->listView->setModel(model);


}

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

这里只实现了和listview的绑定:

 正常显示。

接着绑定了tableview 也正常,还能显示header信息。

 这里不太好理解的是,创建stringlist对象后,他的成员函数好像都没调用,但如果没有的话,估计view是无法正常显示的。试一试。比如把headerdata函数去掉,那么就是:

果不其然,在setmodel的时候,其实这些函数是在生效的。只是不在明面上而已。

如果把rowcount函数略去,则会报错!

所以在子类化的时候,这几个问题还是要注意的。

如果直接使用qabstractitemmodel,也可以实现setmodel,只是数据得一个一个敲上去。

下面试一下如果我改变字符串,是不是能实时更新?

实践证明,list改变后,必须重新setmodel才能更新。

但这样也有个问题,就是每次修改都的重新new一个model,这样是不是很麻烦?

    list<<ui->lineEdit->text();
    delete model;
    model = new StringListModel(list);
    ui->listView->setModel(model);
    ui->tableView->setModel(model);

通过查帮助,发现还有一个qstringlistmodel的对象,试一下:

这个就好用多了嘛,很简单,直接实现:

    QStringList list;
    list<<"我是邋遢大王"<<"我是青蛙公主"<<"我是超级赛亚人";
    model = new QStringListModel(list);
    ui->tableView->setModel(model);

 

经过学习,发现上面的方案确实有问题,应该这样实现:

#include "widget.h"
#include "ui_widget.h"



Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    list<<"我是邋遢大王"<<"我是青蛙公主"<<"我是超级赛亚人";
    model = new QStringListModel(this);
    model->setStringList(list);
    ui->tableView->setModel(model);
    ui->listView->setModel(model);
}

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

void Widget::on_pushButton_clicked()
{
    // 尾部插入空行
    model->insertRow(model->rowCount());
    // 获取最后一行
    QModelIndex index = model->index(model->rowCount()-1,0);
    // 设置显示文字
    model->setData(index,ui->lineEdit->text(),Qt::DisplayRole);
}

说白了,不是每次都new一个新的model,而是同modelindex来实现对model的修改,也不用每次都从stringlist导入数据。看来思路还是很不一样的。

这样,就实现了按钮添加新数据的操作。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Intimes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值