Qt学习笔记13-QStringListModel
QStringListModel
是最简单的模型类,具备向视图提供字符串数据的能力。QStringListModel
是一个可编辑的模型,可以为组件提供一系列字符串作为数据。我们可以将其看作是封装了QStringList
的模型。QStringList
是一种很常用的数据类型,实际上是一个字符串列表(也就是QList<QString>
)。既然是列表,它也就是线性的数据结构,因此,QStringListModel很多时候都会作为QListView
或者QComboBox
这种只有一列的视图组件的数据模型。
下面看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| MyListView::MyListView() { QStringList data; data << "Letter A" << "Letter B" << "Letter C"; model = new QStringListModel(this); model->setStringList(data);
listView = new QListView(this); listView->setModel(model);
QHBoxLayout *btnLayout = new QHBoxLayout; QPushButton *insertBtn = new QPushButton(tr("insert"), this); connect(insertBtn, SIGNAL(clicked()), this, SLOT(insertData())); QPushButton *delBtn = new QPushButton(tr("Delete"), this); connect(delBtn, SIGNAL(clicked()), this, SLOT(deleteData())); QPushButton *showBtn = new QPushButton(tr("Show"), this); connect(showBtn, SIGNAL(clicked()), this, SLOT(showData())); btnLayout->addWidget(insertBtn); btnLayout->addWidget(delBtn); btnLayout->addWidget(showBtn);
QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(listView); mainLayout->addLayout(btnLayout); setLayout(mainLayout); }
|
接下来我们来看几个按钮的响应槽函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void MyListView::insertData() { bool isOK; QString text = QInputDialog::getText(this, "Insert", "Please input new data:", QLineEdit::Normal, "You are inserting new data.", &isOK); if (isOK) { int row = listView->currentIndex().row(); model->insertRows(row, 1); QModelIndex index = model->index(row); model->setData(index, text); listView->setCurrentIndex(index); listView->edit(index); } }
|
首先是insertData()
函数。我们使用QInputDialog::getText()
函数要求用户输入数据。这是 Qt 的标准对话框,用于获取用户输入的字符串。当用户点击了 OK 按钮,我们使用listView->currentIndex()
函数,获取QListView
当前行。这个函数的返回值是一个QModelIndex
类型。
这个类保存了三个重要的数据:行索引、列索引以及该数据属于哪一个模型。我们调用其row()
函数获得行索引,该返回值是一个 int,也就是当前是第几行。然后我们向模型插入新的一行。insertRows()
函数签名如下:
1
| bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
该函数会将 count 行插入到模型给定的 row 的位置,新行的数据将会作为 parent 的子元素。如果 row 为 0,新行将被插入到 parent 的所有数据之前,否则将在指定位置的数据之前。如果 parent 没有子元素,则会新插入一个单列数据。函数插入成功返回 true,否则返回 false。我们在这段代码中调用的是insertRows(row, 1)。这是QStringListModel的一个重载。参数 1 说明要插入 1 条数据。记得之前我们已经把 row 设置为当前行,因此,这行语句实际上是在当前的 row 位置插入 count 行,这里的 count 为 1。由于我们没有添加任何数据,实际效果是,我们在 row 位置插入了 1 个空行。然后我们使用 model 的index()函数获取当前行的QModelIndex对象,利用setData()函数把我们用QInputDialog接受的数据设置为当前行数据。接下来,我们使用setCurrentIndex()函数,把当前行设为新插入的一行,并调用edit()函数,使这一行可以被编辑。
以上是我们提供的一种插入数据的方法:首先插入空行,然后选中新插入的空行,设置新的数据。这其实是一种冗余操作,因为currentIndex()已经获取到当前行。在此,我们仅仅是为了介绍这些函数的使用。因此,除去这些冗余,我们可以使用一种更简洁的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void MyListView::insertData() { bool isOK; QString text = QInputDialog::getText(this, "Insert", "Please input new data:", QLineEdit::Normal, "You are inserting new data.", &isOK); if (isOK) { QModelIndex currIndex = listView->currentIndex(); model->insertRows(currIndex.row(), 1); model->setData(currIndex, text); listView->edit(currIndex); } }
|
接下来是删除数据:
1 2 3 4 5 6
| void MyListView::deleteData() { if (model->rowCount() > 1) { model->removeRows(listView->currentIndex().row(), 1); } }
|
最后是简单地将所有数据都显示出来:
1 2 3 4 5 6 7 8 9
| void MyListView::showData() { QStringList data = model->stringList(); QString str; foreach(QString s, data) { str += s + "\n"; } QMessageBox::information(this, "Data", str); }
|