從本章開始,咱們將逐步瞭解有關自定義模型的相關內容。儘管前面咱們曾經介紹過 Qt 提供的幾個內置模型:QStringListModel
和QFileSystemModel
,但對於變幻無窮的需求而言,這些顯然是遠遠不夠的。因而,Qt 也容許咱們對模型進行自定義。正則表達式
在正式開始介紹自定義模形以前,咱們先來了解一個新的類:QSortFilterProxyModel
。之因此將這個類放在這裏,是由於在必定程序上,咱們可使用QSortFilterProxyModel
得到一些可能必須自定義才能達到的效果。QSortFilterProxyModel
並不能單獨使用。顧名思義,它是一個「代理」,其真正的數據須要另外的一個模型提供。它的做用是對數據進行排序和過濾。排序很好理解,而過濾,則是按照輸入的內容對數據及進行篩選,很像 Excel 裏面的過濾器。不過 Qt 提供的過濾功能是基於正則表達式的,功能很強大。shell
下面咱們根據代碼來了解下QSortFilterProxyModel
的使用:express
#ifndef SORTVIEW_H #define SORTVIEW_H #include <QWidget> #include <QListView> #include <QStringListModel> #include <QSortFilterProxyModel> #include <QComboBox> class SortView : public QWidget { Q_OBJECT public: SortView(); private: QListView *view; QStringListModel *model; QSortFilterProxyModel *modelProxy; QComboBox *syntaxBox; private slots: void filterChanged(const QString &text); }; #endif // SORTVIEW_H
頭文件中,咱們聲明瞭一個類SortView
,繼承自QWidget
。它有四個成員變量以及一個私有槽函數。函數
#include "sortview.h" #include <QLineEdit> #include <QLabel> #include <QHBoxLayout> SortView::SortView() { model = new QStringListModel(QColor::colorNames(), this); modelProxy = new QSortFilterProxyModel(this); modelProxy->setSourceModel(model); modelProxy->setFilterKeyColumn(0); view = new QListView(this); view->setModel(modelProxy); QLineEdit *filterInput = new QLineEdit; QLabel *filterLabel = new QLabel(tr("Filter")); QHBoxLayout *filterLayout = new QHBoxLayout; filterLayout->addWidget(filterLabel); filterLayout->addWidget(filterInput); syntaxBox = new QComboBox; syntaxBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); syntaxBox->addItem(tr("Regular expression"), QRegExp::RegExp); syntaxBox->addItem(tr("Wildcard"), QRegExp::Wildcard); syntaxBox->addItem(tr("Fixed string"), QRegExp::FixedString); QLabel *syntaxLabel = new QLabel(tr("Syntax")); QHBoxLayout *syntaxLayout = new QHBoxLayout; syntaxLayout->addWidget(syntaxLabel); syntaxLayout->addWidget(syntaxBox); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(view); layout->addLayout(filterLayout); layout->addLayout(syntaxLayout); connect(filterInput, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); }
在構造函數中,咱們首先建立一個QStringListModel
對象,其內容是 Qt 預約義的全部顏色的名字(利用QColor::colorNames()
獲取)。而後是QSortFilterProxyModel
對象,咱們將其原模型設置爲剛剛建立的 model,也就是要爲這個 model 進行代理;而後將FilterKeyColumn
設置爲 0,也就是僅僅對第一列進行過濾。咱們使用一個QStringListModel
包裝這個數據,這和前面的內容沒有什麼區別。而後建立一個QSortFilterProxyModel
對象,使用它的setSourceModel()
函數將前面定義的QStringListModel
傳進去,也就是咱們須要對這個 model 進行代理。最後重要的一點是,QListView
的數據源必須設置爲QSortFilterProxyModel
,而不是最開始的 model 對象。工具
做爲過濾選項,syntaxBox 添加了三個數據項:this
syntaxBox->addItem(tr("Regular expression"), QRegExp::RegExp); syntaxBox->addItem(tr("Wildcard"), QRegExp::Wildcard); syntaxBox->addItem(tr("Fixed string"), QRegExp::FixedString);
這正是正則表達式的幾種類型。正則表達式本身有一套相對通用的語法,可是對於不一樣的語言環境(例如 Java、C# 和 Python),其具體定義可能會略有差異。這裏咱們使用的是 Qt 本身的正則表達式處理工具(C++ 自己並無解析正則表達式的機制,雖然 boost 提供了一套)。第一個QregExp::RegExp
提供了最通常的正則表達式語法,但這個語法不支持貪婪限定符。這也是 Qt 默認的規則;若是須要使用貪婪限定符,須要使用QRegExp::RegExp2
。儘管在 Qt4 的文檔中聲明,QRegExp::RegExp2
將會做爲 Qt5 的默認規則,但其實並非這樣。第二個咱們提供的是 Unix shell 常見的一種規則,使用通配符處理。第三個即固定表達式,也就是說基本上不使用正則表達式。代理
接下來咱們看看 filterChanged() 函數的實現:code
void SortView::filterChanged(const QString &text) { QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax( syntaxBox->itemData(syntaxBox->currentIndex()).toInt()); QRegExp regExp(text, Qt::CaseInsensitive, syntax); modelProxy->setFilterRegExp(regExp); }
在這段代碼中,首先使用QComboBox
的選擇值建立一個QRegExp::PatternSyntax
對象;而後利用這個語法規則構造一個正則表達式,注意咱們在QLineEdit
裏面輸入的內容是經過參數傳遞進來的,而後設置數據模型代理的過濾表達式。下面能夠運行一下看看結果:對象
上圖中,咱們輸入的是 gr[ae]y 做爲正則表達式。這是說,咱們但願獲取這樣一個顏色的名字:它的名字中有這樣的四個字母,第一個字母是 g,第二個字母是 r,第三個字母要麼是 a,要麼是 e,第四個字母是 y。若是找到符合條件的名字,就要把它過濾出來,顯示到列表中,不符合條件的所有不顯示。咱們的程序正是這樣的結果。若是你對這個正則表達式不熟悉,請自行查閱有關正則表達式的內容。排序