界面开发框架Qt新手入门 - 自定义排序/筛选模型示例(二)

news/2025/2/14 6:07:54/

Qt 是目前最先进、最完整的跨平台C++开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。

自定义排序/筛选模型示例说明了如何子类化QSortFilterProxyModel来执行高级排序和筛选。

在上文中(点击这里回顾>>),为大家讲解了如何实现MySortFilterProxyModel类、MySortFilterProxyModel的定义,本文将继续讲解Window类的定义和实现!

点击获取Qt Widget组件下载

Window类定义

CustomFilter类继承了QWidget,并提供了这个例子的主应用程序窗口:

class Window : public QWidget
{
Q_OBJECTpublic:
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()(另一个方便的函数)添加到模型中。

 


http://www.ppmy.cn/news/59940.html

相关文章

队列,双端队列,栈结构

java.util.Queue接口.队列 Queue继承自Collection. 队列可以保存一组元素,但是存取元素必须遵循先进先出原则:FIFO(First Input First Output) 常用实现类:LinkedList 双端队列 java.util.Deque Deque继承自Queue 双端队列是队列两端都可以做出入对操作的队列. 常用实现类…

《编程思维与实践》1047.Base64编码

《编程思维与实践》1047.Base64编码 题目 思路 直接模拟:将每个Base64编码值都分为两部分:前半部分由上一个字符求得,后半部分由下一个字符求得. 特别地,如果字符为第一个或最后一个,则直接可以求得Base64编码. 如下图: 其中,% 2 n 2^n 2n表示取出后n位的二进制位, 这是因…

Canny边缘检测算法

文章目录 前言1、Canny边缘检测算法2、代码1函数 3、代码24、基于tensor数据的代码 前言 最近在向卷积神经网络里的数据预处理和数据增强部分加这个函数&#xff0c;记录一下。 1、Canny边缘检测算法 Canny边缘检测算法是一种经典的边缘检测算法&#xff0c;其基本原理如下&a…

git标准使用

git标准使用 首先远程仓库一般只维护两个分支&#xff0c;master和develop。develop在master上创建。master只有项目管理人员才有编辑权限&#xff0c;保存每个正式投入生产环境的版本。 有开发需求的任务时&#xff0c;在dev分支上开feat分支(本地)。在feat分支上完成功能开发…

4 斐波那契数列

4 斐波那契数列 作者: Turbo时间限制: 1S章节: 递归 问题描述 : 斐波那契数列的排列是&#xff1a;0&#xff0c;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89&#xff0c;…

Kafka 消费者

一、消费者工作流程 1.1 总体工作流程 1.2 消费者组初始化流程 1.3 消费者组详细消费流程 二、消费者消费消息方式 ➢ pull&#xff08;拉&#xff09;模 式&#xff1a;consumer采用从broker中主动拉取数据。Kafka采用这种方式。 ➢ push&#xff08;推&#xff09;模式&am…

CommonJS规范

模块化 模块化解决的问题 代码的数量增多导致编写程序复杂度越来越高&#xff0c;此时如果依然将所有的代码编写到同一个文件中&#xff0c;代码就会变得非常难以维护&#xff0c;模块化就说解决这个问题的关键。什么是模块&#xff1f; 模块简单理解就是一个代码片段&#xf…

在一个真实的设备上调试Android应用

由于模拟器只包含很少的应用&#xff0c;可能只有一个处理某个动作的应用。为了更好地测试我们的应用&#xff0c;需要在一个真实的设备上运行这个应用。 可以按一下步骤在一个真实设备上运行你的应用。 1、启动设备上的USB调试选项 在你的安卓设备上&#xff0c;打开开发者选项…