Qt 為我們預(yù)定義了很多 model,前面已經(jīng)說過了 QStringListModel、QDirModel(也算是 Qt 推薦使用的 QFileSystemModel 吧,這個(gè)在上一章最后重新加上了一段話,沒有注意的朋友去看看哦)。今天我們要說的這個(gè) QSortFilterProxyModel 并不能單獨(dú)使用,看它的名字就會(huì)知道,它只是一個(gè)“代理”,真正的數(shù)據(jù)需要另外的一個(gè) model 提供,并且它是用來排序和過濾的。所謂過濾,也就是說按照你輸入的內(nèi)容進(jìn)行數(shù)據(jù)的篩選,很像 Excel 里面的過濾器。不過 Qt 提供的過濾功能是基于正則表達(dá)式的,因而功能強(qiáng)大。
我們從代碼開始看起:
sortview.h
#ifndef SORTVIEW_H
#define SORTVIEW_H
#include <QtGui>
class SortView : public QWidget
{
Q_OBJECT
public:
SortView();
private:
QListView *view;
QStringListModel *model;
QSortFilterProxyModel *modelProxy;
QComboBox *syntaxBox;
private slots:
void filterChanged(QString text);
};
#endif // SORTVIEW_H
sortview.cpp
#include "sortview.h"
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)));
}
void SortView::filterChanged(QString text)
{
QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(
syntaxBox->itemData(syntaxBox->currentIndex()).toInt());
QRegExp regExp(text, Qt::CaseInsensitive, syntax);
modelProxy->setFilterRegExp(regExp);
}
至于 main()函數(shù)的內(nèi)容,由于和前面的代碼幾乎是一樣的,這里就不再貼出來了。我們使用的是QColor::colorNames()函數(shù)提供的數(shù)據(jù)。這個(gè)函數(shù)返回值是一個(gè)QStringList 類型的變量,可以給出預(yù)定義的顏色的名字。我們使用一個(gè)QStringListModel 包裝這個(gè)數(shù)據(jù),這和前面的內(nèi)容沒有什么區(qū)別。然后創(chuàng)建一個(gè)QSortFilterProxyModel 對(duì)象,使用它的 setSourceModel()函數(shù)將前面定義的QStringListModel 傳進(jìn)去,也就是我們需要對(duì)這個(gè) model 進(jìn)行代理。那么我們需要過濾哪一列呢?雖然 QStringListModel 只有一列,但是我們也需要使用 setFilterKeyColumn()函數(shù)設(shè)置一下,以便讓這個(gè) proxy 知道要過濾的是第0列。最后重要的一點(diǎn)是,QListView 的 model 必須設(shè)置為QSortFilterProxyModel,否則是看不到效果的。
下面的 QLineEdit 提供過濾數(shù)據(jù)的輸入,這個(gè)沒什么好說的。后面的 QComboBox 列出了三項(xiàng):
syntaxBox->addItem(tr("Regular expression"), QRegExp::RegExp);
syntaxBox->addItem(tr("Wildcard"), QRegExp::Wildcard);
syntaxBox->addItem(tr("Fixed string"), QRegExp::FixedString);
這是正則表達(dá)式的類型。正則表達(dá)式有一套通用的語法,但是對(duì)于不同的環(huán)境,正則表達(dá)式的規(guī)則可能是不一樣的。第一個(gè) QregExp::RegExp 提供了最一般的正則表達(dá)式語法,不過這個(gè)語法不支持貪婪限定符。這也是 Qt 默認(rèn)的規(guī)則。如果你需要使用貪婪限定符,需要使用 QRegExp::RegExp2,根據(jù)文檔描述,這個(gè)將會(huì)是 Qt5 的默認(rèn)規(guī)則。第二個(gè)是 Unix 下 shell 很常見的一種規(guī)則。第三個(gè)即固定表達(dá)式,也就是說基本上不使用正則表達(dá)式的。
我們使用 connect()函數(shù),將 QLineEdit 的 textChanged()信號(hào)同 slot 連接起來。其中我們的slot 函數(shù)如下所示:
void SortView::filterChanged(QString text)
{
QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(
syntaxBox->itemData(syntaxBox->currentIndex()).toInt());
QRegExp regExp(text, Qt::CaseInsensitive, syntax);
modelProxy->setFilterRegExp(regExp);
}
第一步,使用 QComboBox 的選擇值創(chuàng)建一個(gè) QRegExp::PatternSyntax 對(duì)象,然后利用這個(gè)語法規(guī)則構(gòu)造一個(gè)正則表達(dá)式,注意我們?cè)?QLineEdit 里面輸入的內(nèi)容是通過參數(shù)傳遞進(jìn)來的,然后設(shè)置proxy 的過濾器的表達(dá)式。好了,就這樣運(yùn)行一下看看效果吧!
本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/193918
更多建議: