1. Introduction to Model/View Programming
Qt 4 introduced a new set of item view classes that use a model/view architecture(结构) to manage the relationship between data and the way it is presented to the user.2.Models
All item models are based on the QAbstractItemModel class. This class defines an interface that is used by views and delegates(委托) to access data. The data itself does not have to be stored in the model; it can be held(保留) in a data structure or repository(仓库) provided by a separate class, a file, a database, or some other application component.
3. Qt provides some ready-made models that can be used to handle items of data:
- QStringListModel is used to store a simple list of QString items.
- QStandardItemModel manages more complex tree structures of items, each of which can contain arbitrary data.
- QFileSystemModel provides information about files and directories in the local filing system.
- QSqlQueryModel, QSqlTableModel, and QSqlRelationalTableModel are used to access databases using model/view conventions.
If these standard models do not meet your requirements, you can subclass QAbstractItemModel, QAbstractListModel, or QAbstractTableModel to create your own custom models.
Such as:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSplitter *splitter = new QSplitter;
QFileSystemModel *model = new QFileSystemModel;
model->setRootPath(QDir::currentPath());
QTreeView *tree = new QTreeView(splitter);
tree->setModel(model);
tree->setRootIndex(model->index(QDir::currentPath()));
QListView *list = new QListView(splitter);
list->setModel(model);
list->setRootIndex(model->index(QDir::currentPath()));
splitter->setWindowTitle("Two views onto the same file system model");
splitter->show();
return a.exec();
}
4. Basic concepts
In the model/view architecture, the model provides a standard interface that views and delegates use to access data. In Qt, the standard interface is defined by theQAbstractItemModel class. No matter how the items of data are stored in any underlying data structure, all subclasses of QAbstractItemModel represent the data as a hierarchical structure containing tables of items. Views use this convention to access items of data in the model, but they are not restricted in the way that they present this information to the user.
As a result, only the model needs to know how to obtain data, and the type of data managed by the model can be defined fairly generally. Model indexes contain a pointer to the model that created them, and this prevents confusion when working with more than one model.
QAbstractItemModel *model = index.model();
5 Using a model
We take the string list model that we created as an example model, set it up with some data, and construct a view to display the contents of the model. This can all be performed within a single function:
QStringList numbers;
numbers << "One" << "Two" << "Three" << "Four" << "Five";
QAbstractItemModel *model = new StringListModel(numbers);
QListView *view = new QListView;
view->setModel(model);
view->show();
.h file:
class StringListModel : public QAbstractListModel
{
Q_OBJECT
public:
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;
private:
QStringList stringList;
};
.cpp file:
int StringListModel::rowCount(const QModelIndex &parent) const
{
return stringList.count();
}
QVariant StringListModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid()) ///valid: 有效的
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);
}