Qt學習之路(42): QStringListModel

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://devbean.blog.51cto.com/448512/265057

今天開始我們要看看Qt的model-view類了。正如前面說的那樣,之前三節的item class類只是Qt爲了方便我們使用而封裝了的一些操作。比起真正的model-view類來,那些類更易於使用,但是功能也會更簡單,並且缺少實時性的支持,比如我們並不方便實現插入、刪除等一些常見操作。而現在我們要說的model-view類使用起來可能會複雜一些,但是功能強大,並且在model更新時會自動更新view,而model多是一些數據集合,因此比較便於操作。

 

model-view類中,view大致有三種:list、tree和table,但是model千奇百怪,不同的業務,甚至同樣的業務不同的建模都會有不同的model。爲了方便使用,Qt提供了一些預定義好的model供我們使用。QStringListModel是其中最簡單的一種。

 

顧名思義,QStringListModel就是封裝了QStringList的model。QStringList是一種很常用的數據類型,它實際上是一個字符串列表。我們可以想象,對於一個list來說,如果提供一個字符串列表形式的數據,就應該能夠把這個數據展示出來。因爲二者是一致的:QStringList是線性的,而list也是線性的。所以,QStringListModel很多時候都會作爲QListView的model。

 

下面我們來看怎麼使用它們。比起前面的QListWidget,這裏要使用兩個類:QStringListModel和QListView,並且還有一些輔助類。不過你可以看到,即便這樣複雜的工作,我們的代碼也不會很多的:

 

mylistview.h

#ifndef MYLISTVIEW_H 
#define MYLISTVIEW_H 
 
#include <QtGui> 
 
class MyListView : public QWidget 

        Q_OBJECT 
public
        MyListView(); 
 
private
        QStringListModel *model; 
        QListView *listView; 
 
private slots: 
        void insertData(); 
        void deleteData(); 
        void showData(); 
}; 
 
#endif // MYLISTVIEW_H

 

mylistview.cpp

#include "mylistview.h" 
 
MyListView::MyListView() 

        model = new QStringListModel(this); 
        QStringList data; 
        data << "Letter A" << "Letter B" << "Letter C"
        model->setStringList(data); 
        listView = new QListView(this); 
        listView->setModel(model); 
        QHBoxLayout *btnLayout = new QHBoxLayout; 
        QPushButton *insertBtn = new QPushButton(tr("insert"), this); 
        QPushButton *delBtn = new QPushButton(tr("Delete"), this); 
        QPushButton *showBtn = new QPushButton(tr("Show"), this); 
        btnLayout->addWidget(insertBtn); 
        btnLayout->addWidget(delBtn); 
        btnLayout->addWidget(showBtn); 
        QVBoxLayout *mainLayout = new QVBoxLayout(this); 
        mainLayout->addWidget(listView); 
        mainLayout->addLayout(btnLayout); 
        this->setLayout(mainLayout); 
 
        connect(insertBtn, SIGNAL(clicked()), this, SLOT(insertData())); 
        connect(delBtn, SIGNAL(clicked()), this, SLOT(deleteData())); 
        connect(showBtn, SIGNAL(clicked()), this, SLOT(showData())); 

 
void MyListView::insertData() 

        bool isOK; 
        QString text = QInputDialog::getText(NULL, "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); 
        } 

 
void MyListView::deleteData() 

        if(model->rowCount() > 1) { 
                model->removeRows(listView->currentIndex().row(), 1); 
        } 

 
void MyListView::showData() 

        QStringList data = model->stringList(); 
        QString str; 
        foreach(QString s, data) { 
                str += s + "\n"
        } 
 
        QMessageBox::information(this"Data", str); 

 

 

來看看我們的代碼吧。

 

首先我們創建一個QStringListModel的對象。然後創建一個QStringList對象,並且把這個對象設置爲model的數據。此時,這個model已經擁有數據了。然後,我們創建一個QListView的對象,並把model設置爲它的model。後面是三個按鈕的創建以及信號槽的連接,這裏就不再贅述。

 

先來運行一下看看結果吧!

 

我們只是把QStringListModel設置爲QListView的model,QListView就已經可以把model裏面的數據展示出來了。下面我們看看增、刪、改的操作。

 

先來看增加數據的操作。這部分是在代碼中的insertData()函數實現的。先把那個函數拿出來看看:

 

void MyListView::insertData() 

        bool isOK; 
        QString text = QInputDialog::getText(NULL, "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); 
        } 
}

 

我們使用QInputDialog::getText()函數要求用戶輸入數據。這部分在前面講過,這裏也不再贅述。如果用戶點擊了OK按鈕,首先,我們使用listView()->currentIndex()函數,獲取QListView當前行。注意,這個函數的返回值是一個QModelIndex類型。這個類我們以後再說,只要知道這個類保存了三個重要的數據:行、列以及屬於哪一個model。我們調用其row()函數獲得行,這個返回值是一個int,也就是第幾行。然後model插入一行。insertRows()函數簽名如下:

 

bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());

 

這個函數原本是QAbstractListModel類的函數,而QStringListModel把它覆蓋了。所以我們會發現它還需要另外的一個參數。我們調用 insertRows(row, 1); ,所謂1就是指插入1條數據,而前面又把row保存成當前行,因此,這行語句實際上是在當前的 row 行插入 count 行,這裏的 count = 1。然後我們使用model的index()函數獲取當前行的QModelIndex對象,使用setData()函數把我們用QInputDialog接受的數據插入。這裏其實是一個冗餘的操作,因爲用currentIndex()函數已經獲取當前行了。這麼寫僅僅是爲了展示如何使用這個函數。不過,你知道了insertRow()函數,就可以很容易的做出插入空白行的效果了。然後我們把當前行設爲新插入的一行,並調用edit()函數,這個函數使得這一行可以被編輯。就這樣,我們向model插入了數據。

 

然後來看刪除數據的操作:

 

void MyListView::deleteData() 

        if(model->rowCount() > 1) { 
                model->removeRows(listView->currentIndex().row(), 1); 
        } 
}

 

使用model的removeRows()函數可以輕鬆的完成這個功能。這個函數同前面所說的insertRows()很類似,就不再多說了。需要注意的是,我們用rowCount()函數判斷了一下,要求最終始終保留1行。這是因爲如果你把數據全部刪除,你就不能再插入數據了,因爲那時侯按照我們所寫的插入邏輯就不對了。所以,前面所說的插入操作實際上還需要再詳細考慮。

 

最後那個showData()僅僅爲了查看model的數據,沒有什麼要說的東西。你可以在insert或者remove完成後查看一下model裏面的數據是不是真的被修改了。

 

關於QStringListModel就說這麼多。你可以看到,我們的幾乎所有操作都是針對model的,也就是說,我們直接針對的是數據,而model偵測到數據發生了變化,會立刻通知view刷新。這樣,我們就可以把精力集中到對數據的操作上,而不用擔心view的同步等操作。這也是model-view模型的一個便捷之處。

本文出自 “豆子空間” 博客,請務必保留此出處http://devbean.blog.51cto.com/448512/265057


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章