自定义模型CityModel

  参考<<C++ GUI Programming with Qt 4>>中文版第二版中的例子:城市距离。具体描述请看书本,主要重写继承自QAbstractTableModel的CityModel,该模型底层的数据是一个QStringList类型的对象和一个QVector<int>类型的对象。前者用于保存城市的名字,后者保存城市之间的距离。

  citymodel.h文件:

#ifndef CITYMODEL_H
#define CITYMODEL_H

#include <QAbstractTableModel>
#include <QVector>
#include <QStringList>

class CityModel : public QAbstractTableModel
{
public:
    CityModel(QObject *parent = 0);
    void setCities(const QStringList &cityNames);
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;

    Qt::ItemFlags flags(const QModelIndex &index) const;

private:
    int offsetOf(int row, int column) const;
    QStringList cities;
    QVector<int> distances;
};

#endif

  citymodel.cpp文件:

#include "citymodel.h"

CityModel::CityModel(QObject *parent)
    :QAbstractTableModel(parent)
{
}

int CityModel::rowCount(const QModelIndex &parent) const
{
    return cities.count();
}

int CityModel::columnCount(const QModelIndex &parent) const
{
    return cities.count();
}

QVariant CityModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
    {
        return QVariant();
    }
    if (role == Qt::TextAlignmentRole)
    {
        return int(Qt::AlignRight | Qt::AlignVCenter);
    }
    else if (role == Qt::DisplayRole)
    {
        if (index.row() == index.column())
        {
            return 0;
        }
        int offset = offsetOf(index.row(), index.column());
        return distances[offset];
    }
    return QVariant();
}

QVariant CityModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
    {
        return cities[section];
    }
    return QVariant();
}

bool CityModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && index.row() != index.column() && role == Qt::EditRole)
    {
        int offset = offsetOf(index.row(), index.column());
        distances[offset] = value.toInt();
        QModelIndex transposedIndex = createIndex(index.column(), index.row());

        emit dataChanged(index, index);
        emit dataChanged(transposedIndex, transposedIndex);
        return true;
    }
    return false;
}

Qt::ItemFlags CityModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags = QAbstractItemModel::flags(index);
    if (index.row() != index.column())
    {
        flags |= Qt::ItemIsEditable;
    }
    return flags;
}

void CityModel::setCities(const QStringList &cityNames)
{
    cities = cityNames;
    distances.resize(cities.count() * (cities.count() - 1)/2);
    distances.fill(0);
    reset();
}

int CityModel::offsetOf(int row, int column) const
{
    if (row < column)
    {
        qSwap(row, column);
    }
    return (row * (row - 1)/2) + column;
}

  main.cpp文件:

#include <QtGui/QApplication>
#include "citymodel.h"
#include <QTableView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QStringList cities;
    cities<<"Arvika"<<"Boden"<<"Eskilstuna"<<"Falun"<<"Filipstad";
    CityModel cityModel;
    cityModel.setCities(cities);

    QTableView tableView;
    tableView.setModel(&cityModel);
    tableView.setAlternatingRowColors(true);
    tableView.setWindowTitle("cities");
    tableView.show();

    return a.exec();
}

  运行界面:

                         

posted @ 2012-10-20 09:39  venow  阅读(1083)  评论(0编辑  收藏  举报