天天看點

界面開發架構Qt新手入門 - 自定義排序/篩選模型示例(二)

作者:慧都科技

Qt 是目前最先進、最完整的跨平台C++開發工具。它不僅完全實作了一次編寫,所有平台無差别運作,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用于超過70個行業、數千家企業,支援數百萬裝置及應用。

自定義排序/篩選模型示例說明了如何子類化QSortFilterProxyModel來執行進階排序和篩選。

界面開發架構Qt新手入門 - 自定義排序/篩選模型示例(二)

在上文中為大家講解了如何實作MySortFilterProxyModel類、MySortFilterProxyModel的定義,本文将繼續講解Window類的定義和實作!

Window類定義

CustomFilter類繼承了QWidget,并提供了這個例子的主應用程式視窗:

class Window : public QWidget
{
Q_OBJECT

public:
Window();

void setSourceModel(QAbstractItemModel *model);

private slots:
void textFilterChanged();
void dateFilterChanged();

private:
MySortFilterProxyModel *proxyModel;

QGroupBox *sourceGroupBox;
QGroupBox *proxyGroupBox;
QTreeView *sourceView;
QTreeView *proxyView;
QLabel *filterPatternLabel;
QLabel *fromLabel;
QLabel *toLabel;
FilterWidget *filterWidget;
QDateEdit *fromDateEdit;
QDateEdit *toDateEdit;
};           

我們實作了兩個私有槽,textFilterChanged()和dateFilterChanged(),用于響應使用者更改過濾器模式、區分大小寫或任何日期,此外還實作了一個公共的setSourceModel()友善函數來設定模型/視圖關系。

Window類實作

在本示例中,我們選擇在main()函數中建立和設定源模型,是以在建構主應用程式視窗時,假設源模型已經存在,并從建立自定義代理模型的執行個體開始:

Window::Window()
{
proxyModel = new MySortFilterProxyModel(this);           

我們設定dynamicSortFilter屬性,該屬性儲存代理模型是否被動态排序和過濾。通過将該屬性設定為true,可以確定在源模型的内容發生變化時對模型進行排序和過濾。

主應用程式視窗顯示源模型和代理模型的視圖,源視圖非常簡單:

sourceView = new QTreeView;
sourceView->setRootIsDecorated(false);
sourceView->setAlternatingRowColors(true);           

QTreeView類提供了樹視圖的預設模型/視圖實作,視圖實作了應用程式源模型中項目的樹表示。

sourceLayout->addWidget(sourceView);
sourceGroupBox = new QGroupBox(tr("Original Model"));
sourceGroupBox->setLayout(sourceLayout);           

QTreeView 類提供了樹視圖的預設模型/視圖實作,視圖實作了應用程式源模型中項目的樹表示,将視圖小部件添加到我們安裝在相應組框上的布局中。

另一方面代理模型視圖包含幾個控件,這些控件控制轉換源模型資料結構的各個方面:

filterWidget = new FilterWidget;
filterWidget->setText(tr("Grace|Sports"));
connect(filterWidget, &FilterWidget::filterChanged, this, &Window::textFilterChanged);

filterPatternLabel = new QLabel(tr("&Filter pattern:"));
filterPatternLabel->setBuddy(filterWidget);

fromDateEdit = new QDateEdit;
fromDateEdit->setDate(QDate(1970, 01, 01));
fromLabel = new QLabel(tr("F&rom:"));
fromLabel->setBuddy(fromDateEdit);

toDateEdit = new QDateEdit;
toDateEdit->setDate(QDate(2099, 12, 31));
toLabel = new QLabel(tr("&To:"));
toLabel->setBuddy(toDateEdit);

connect(filterWidget, &QLineEdit::textChanged,
this, &Window::textFilterChanged);
connect(fromDateEdit, &QDateTimeEdit::dateChanged,
this, &Window::dateFilterChanged);
connect(toDateEdit, &QDateTimeEdit::dateChanged,
this, &Window::dateFilterChanged);           

請注意,每當使用者更改其中一個過濾選項時,我們必須顯式地重新應用該過濾器,這是通過将各種編輯器連接配接到更新代理模型的函數來完成的。

proxyView = new QTreeView;
proxyView->setRootIsDecorated(false);
proxyView->setAlternatingRowColors(true);
proxyView->setModel(proxyModel);
proxyView->setSortingEnabled(true);
proxyView->sortByColumn(1, Qt::AscendingOrder);

QGridLayout *proxyLayout = new QGridLayout;
proxyLayout->addWidget(proxyView, 0, 0, 1, 3);
proxyLayout->addWidget(filterPatternLabel, 1, 0);
proxyLayout->addWidget(filterWidget, 1, 1);
proxyLayout->addWidget(fromLabel, 3, 0);
proxyLayout->addWidget(fromDateEdit, 3, 1, 1, 2);
proxyLayout->addWidget(toLabel, 4, 0);
proxyLayout->addWidget(toDateEdit, 4, 1, 1, 2);

proxyGroupBox = new QGroupBox(tr("Sorted/Filtered Model"));
proxyGroupBox->setLayout(proxyLayout);           

排序将由視圖處理,我們所要做的就是通過設定QTreeView::sortingEnabled屬性(預設為false)來啟用代理視圖的排序。然後,我們将所有過濾小部件和代理視圖添加到安裝在相應組框上的布局中。

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(sourceGroupBox);
mainLayout->addWidget(proxyGroupBox);
setLayout(mainLayout);

setWindowTitle(tr("Custom Sort/Filter Model"));
resize(500, 450);
}           

最後,在将兩個組框放入安裝在主應用程式小部件上的另一個布局中之後,自定義應用程式視窗。

如上所述,在main()函數中建立源模型,調用Window::setSourceModel()函數使應用程式使用它:

void Window::setSourceModel(QAbstractItemModel *model)
{
proxyModel->setSourceModel(model);
sourceView->setModel(model);

for (int i = 0; i < proxyModel->columnCount(); ++i)
proxyView->resizeColumnToContents(i);
for (int i = 0; i < model->columnCount(); ++i)
sourceView->resizeColumnToContents(i);
}           

QSortFilterProxyModel::setSourceModel()函數使代理模型處理給定模型中的資料,在本例中是郵件模型,視圖小部件從QAbstractItemModel 類繼承的setModel() 為視圖設定要呈現的模型。注意,後一個函數還将建立和設定一個新的選擇模型。

void Window::textFilterChanged()
{
FilterWidget::PatternSyntax s = filterWidget->patternSyntax();
QString pattern = filterWidget->text();
switch (s) {
case FilterWidget::Wildcard:
pattern = QRegularExpression::wildcardToRegularExpression(pattern);
break;
case FilterWidget::FixedString:
pattern = QRegularExpression::escape(pattern);
break;
default:
break;
}

QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
if (filterWidget->caseSensitivity() == Qt::CaseInsensitive)
options |= QRegularExpression::CaseInsensitiveOption;
QRegularExpression regularExpression(pattern, options);
proxyModel->setFilterRegularExpression(regularExpression);
}           

每當使用者更改過濾器模式或區分大小寫時,就調用textFilterChanged()函數。

首先檢索首選文法(FilterWidget::PatternSyntax enum用于解釋給定模式的含義),然後确定首選的大小寫敏感性。基于這些參數和目前的過濾器模式,我們設定代理模型的filterRegularExpression 屬性。filterRegularExpression 屬性儲存用于過濾源模型内容的正規表達式,注意調用QSortFilterProxyModel的setfilterregulareexpression()函數也會更新模型。

void Window::dateFilterChanged()
{
proxyModel->setFilterMinimumDate(fromDateEdit->date());
proxyModel->setFilterMaximumDate(toDateEdit->date());
}           

每當使用者修改有效日期範圍時,就調用dateFilterChanged()函數,從使用者界面檢索新的日期,并調用相應的函數(由自定義代理模型提供)來設定代理模型的最小和最大日期。如上所述,調用這些函數也會更新模型。

Main()函數

在本例中我們通過在main()函數中建立模型,将應用程式與源模型分離開來。首先我們建立應用程式,然後建立源模型:

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window window;
window.setSourceModel(createMailModel(&window));
window.show();
return app.exec();
}           

createMailModel()函數是為簡化構造函數而提供的友善函數,它所做的就是建立并傳回一個描述電子郵件集合的模型。該模型是QStandardItemModel類的一個執行個體,也就是說,一個用于存儲自定義資料的通用模型,通常用作标準Qt資料類型的存儲庫,每個郵件描述都使用addMail()(另一個友善的函數)添加到模型中。

Qt Widget元件推薦

  • QtitanRibbon - Ribbon UI元件:是一款遵循Microsoft Ribbon UI Paradigm for Qt技術的Ribbon UI元件,QtitanRibbon緻力于為Windows、Linux和Mac OS X提供功能完整的Ribbon元件。
  • QtitanChart - Qt類圖表元件:是一個C ++庫,代表一組控件,這些控件使您可以快速地為應用程式提供漂亮而豐富的圖表。
  • QtitanDataGrid - Qt網格元件:提供了一套完整的标準 QTableView 函數和傳統元件無法實作的獨特功能。使您能夠将不同來源的各類資料加載到一個快速、靈活且功能強大的可編輯網格中,支援排序、分組、報告、建立帶狀列、拖放按鈕和許多其他友善的功能。
  • QtitanDocking:允許您像 Visual Studio 一樣為您的偉大應用程式配備可停靠面闆和可停靠工具欄。黑色、白色、藍色調色闆完全支援 Visual Studio 2019 主題!

繼續閱讀