【转载】10.2 使用预定义模型(Using Predefined Models)

本文介绍了Qt框架中预定义的模型使用,包括QStringListModel、QDirModel和QSortFilterProxyModel。通过示例展示了如何创建和操作这些模型,如在对话框中编辑字符串列表、查看和操作文件目录以及实现过滤和排序功能。通过理解这些模型,开发者可以更好地利用Qt进行数据展示和用户交互。
摘要由CSDN通过智能技术生成

对使用视图类Qt提供了几种预定义的模型:

QStringListModel

保存串列表

QStandardItemModel

保存随机层次结构数据

QDirModel

封装本地文件系统

QSqlQueryModel

封装一个SQL结果集

QSqlTableModel

封装一个SQL

QSqlRelationalTableModel

封装一个带外键的 SQL

QSortFilterProxyModel

保存 and/or过滤另一模型

在本节,我们将说明如何使用QStringListModelQDirModelQSortFilterProxyModelSQL模型在第十三章说明。

首先看一个简单对话框,用户使用该对话框来添加、删除、编辑一个QStringList,其中每个串表示一个团队领导。

Figure 10.6. The Team Leaders application

TeamLeadersDialog::TeamLeadersDialog(const QStringList &leaders,

                                     QWidget *parent)

    : QDialog(parent)

{

    model = new QStringListModel(this);

    model->setStringList(leaders);

    listView = new QListView;

    listView->setModel(model);

    listView->setEditTriggers(QAbstractItemView::AnyKeyPressed

                              | QAbstractItemView::DoubleClicked);

    ...

}

 

首先创建一个QStringListModel。然后创建一个QListView并设置其模型为刚刚创建的QStringListModel模型。设置一些编辑触发器允许用户只开始输入或双击就可以编辑一个串。默认,QListView上没有设置编辑触发器,这样可以使视图有效地只读浏览。

void TeamLeadersDialog::insert()

{

    int row = listView->currentIndex().row();

    model->insertRows(row, 1);

    QModelIndex index = model->index(row);

    listView->setCurrentIndex(index);

    listView->edit(index);

}

 

当用户点击Insert按钮时,会调用insert()槽。一开始会获得列表视图当前项的行号。模型中每个数据项有对应的“模型索引”,它用一个QModelIndex对象表示。一个索引有三个主要组成部分:行、列、指向所属模型的指针。对一个一维列表模型,列总为0

一旦我们有了行号,我们就在该位置插入一个新行。插入在该模型中执行,模型自动更新列表视图。然后我们设置列表视图的当前索引为刚插入的空行。最后,我们设置列表视图为新行上的编辑模式,就好像用户已经输入一个键或双击来启动编辑。

void TeamLeadersDialog::del()
{
    model->removeRows(listView->currentIndex().row(), 1);
}

 

在构造函数中,Delete按钮的clicked()信号是与del()槽相连。由于我们只是删除当前行,我们就调用removeRows(),参数为当前索引位置及行数1。同插入一样,模型自动更新视图。

QStringList TeamLeadersDialog::leaders() const
{
    return model->stringList();
}

 

最后,leaders()函数提供一种方式:当对话框关闭时返回编辑的串。

TeamLeadersDialog只用改变窗口标题就能被用作一个通用的串列表编辑对话框。另一个常用对话框是表示文件或目录的列表。下面的例子使用QDirModel类,它封装了计算机的文件系统并且能显示和隐藏各种文件属性。该模型使用了一个过滤器来限制显示的文件系统的种类,而且可以用不同方式排序。

Figure 10.7. The Directory Viewer application

DirectoryViewer::DirectoryViewer(QWidget *parent)

    : QDialog(parent)

{

    model = new QDirModel;

    model->setReadOnly(false);

    model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);

    treeView = new QTreeView;

    treeView->setModel(model);

    treeView->header()->setStretchLastSection(true);

    treeView->header()->setSortIndicator(0, Qt::AscendingOrder);

    treeView->header()->setSortIndicatorShown(true);

    treeView->header()->setClickable(true);

    QModelIndex index = model->index(QDir::currentPath());

    treeView->expand(index);

    treeView->scrollTo(index);

    treeView->resizeColumnToContents(0);

    ...

}

一旦模型被创建,我们将它设为可编辑的并设置各种初始排序属性。然后我们创建QtreeView来显示模型数据。QtreeView的头能用于提供用户控制的排序。通过使头部为可点击的,用户通过所点击的任意列头能进行排序,可以重复点击升序或降序排序。一旦树型视图的头被设置,我们得到当前目录的模型索引,并确保目录是可见的,必要时用expand()来展开它的父亲并用scrollTo()来滚动到它的位置。然后我们要确保第一列足够宽不需要用省略号可以显示所有的实例。

在构造函数此处没有显示的代码,我们是连接Create DirectoryRemove按钮到槽。我们不需要Rename按钮因为用户可以按F2键和输入来进行重命名。

void DirectoryViewer::createDirectory()

{

    QModelIndex index = treeView->currentIndex();

    if (!index.isValid())

        return;

    QString dirName = QInputDialog::getText(this,

                              tr("Create Directory"),

                              tr("Directory name"));

    if (!dirName.isEmpty()) {

        if (!model->mkdir(index, dirName).isValid())

            QMessageBox::information(this, tr("Create Directory"),

                    tr("Failed to create the directory"));

    }

}

 

如果用户在输入对话框中输入了目录名,我们就用该名字创建一个目录来作为当前目录的孩。QDirModel::mkdir()函数接收父目录的索引及新目录的名字,返回所创建的目录的模型索引。如果该操作失败,返回一个无效的模型索引。

void DirectoryViewer::remove()

{

    QModelIndex index = treeView->currentIndex();

    if (!index.isValid())

        return;

    bool ok;

    if (model->fileInfo(index).isDir()) {

        ok = model->rmdir(index);

    } else {

        ok = model->remove(index);

    }

    if (!ok)

        QMessageBox::information(this, tr("Remove"),

                tr("Failed to remove %1").arg(model->fileName(index)));

}

 

如果用户点击了Remove,我们将删除与当前项有关的文件或目录。本可以用QDir来完成删除,但QDirModel提供了基于QModelIndexes的更方便的接口。

本节最后一个例子说明如何使用QSortFilterProxyModel。不同于其它预定义模型,该模型封装了一个存在的模型并操作在模型和视图间所传递的数据。本例中,下面的模型是一个QStringListModel,用QColor::colorNames()获得的颜色名字来初始化。用户可以在QLineEdit中输入一个过滤串,用一个combobox指定如何解释该串(作为常规表达,通配符,或是一个固定串)。

Figure 10.8. The Color Names application

ColorNamesDialog::ColorNamesDialog(QWidget *parent)

    : QDialog(parent)

{

    sourceModel = new QStringListModel(this);

    sourceModel->setStringList(QColor::colorNames());

    proxyModel = new QSortFilterProxyModel(this);

    proxyModel->setSourceModel(sourceModel);

    proxyModel->setFilterKeyColumn(0);

    listView = new QListView;

    listView->setModel(proxyModel);

    ...

    syntaxComboBox = new QComboBox;

    syntaxComboBox->addItem(tr("Regular expression"), QRegExp::RegExp);

    syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard);

    syntaxComboBox->addItem(tr("Fixed string"), QRegExp::FixedString);

    ...

}

用常用方式创建QStringListModel,接着创建一个QSortFilterProxyModel。用setSourceModel()传递这个模型并告诉代理根据原始模型的0列过滤。QComboBox::addItem()函数接收一个可选的QVariant 类型的“数据”参数。我们使用它来保存与每项文本对应的QRegExp::PatternSyntax值。

void ColorNamesDialog::reapplyFilter()

{

    QRegExp::PatternSyntax syntax =

            QRegExp::PatternSyntax(syntaxComboBox->itemData(

                    syntaxComboBox->currentIndex()).toInt());

    QRegExp regExp(filterLineEdit->text(), Qt::CaseInsensitive, syntax);

    proxyModel->setFilterRegExp(regExp);

}

 

当用户改变过滤串或时pattern syntax combobox 时会调用reapplyFilter()槽。我们使用行编辑中的文本创建一个QRegExp。然后我们设置它的模式语法为一个保存在该combobox的当前项数据。当调用setFilterRegExp()时,新的过滤器激活且自动更新视图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值