博主QQ:1356438802

选择是视图中经常使用的一个操作。在列表、树或者表格中,通过鼠标点击能够选中某一项,被选中项会变成高亮或者反色。在 Qt 中,选择也是使用了一种模型。在 model/view 架构中,这样的选择模型提供了一种更通用的对选择操作的描写叙述。

对于一般应用而言。Qt 内置的选择模型已经足够。可是。Qt 还是同意你创建自己的选择模型,来实现一些特殊的操作。

Qt 使用QItemSelectionModel类获取视图中项目的选择情况。这个模型保持有项目的索引。而且独立于不论什么视图。这意味着,我们能够让不同的视图共享同一个选择模型,从来达到一种同步操作的目的。选择由选择区域组成。模型仅仅将选区的開始和结束的索引位置记录下来,以保证对于非常大的选区也有非常好的性能。

非连续选区则由多个连续选择组成。

选择会直接应用于选择模型所维护的那些被选中的索引上面。最新的选择就是当前选择。这意味着。即便界面上没有显示有不论什么项目被选择。假设通过某些命令对选区进行操作,相同会有作用。

在视图中,始终存在一个当前项和被选择项(即便从界面上看不到有不论什么选择)。与通常所想的不同,当前项和选择项是相互独立的两个状态。一个项目能够即是当前项又是选择项。下表是当前项和选择项的差别:

当前项 选择项
仅仅能有一个当前项。 能够有多个选择项。
使用键盘或者鼠标点击能够改变当前项。 选择项使用两种状态:选择和未选择,这取决于项目之前的状态和其他一些设置。比如,单选或多选。仅仅有在用户进行交互的时候,这样的状态才会发生改变。
当前项能够使用 F2 或者鼠标双击进行编辑(前提是程序同意)。

当前项能够结合另外一个锚点指定被选择或者去除选择的一块选区(或二者的结合)。

当前项一般会有一个焦点框进行标识。 选择项使用选区颜色进行标识。

在处理选择的时候,我们能够将QItemSelectionModel当成数据模型中全部数据项的选择状态的一个记录。

一旦选择模型创建好,这些数据项就能够在不知道哪些项被选择的情况下进行选择、取消选择或者改变选择状态的操作。全部被选择项的索引都在可随时更改,其他组件也能够通过信号槽机制改动这些选择的信息。

标准视图类(QListViewQTreeView以及QTableView)已经提供了默认的选择模型,足以满足大多数应用程序的需求。

某一个视图的选择模型能够通过selectionModel()函数获取,然后使用setSelectionModel()提供给其他视图共享,因此,一般没有必要新建选择模型。

假设须要创建一个选区。我们须要指定一个模型以及一对索引,使用这些数据创建一个QItemSelection对象。这两个索引应该指向给定的模型中的数据,而且作为一个块状选区的左上角和右下角的索引。为了将选区应用到模型上。须要将选区提交到选择模型。

这样的操作有多种实现,对于现有选择模型有着不同的影响。

以下我们来看一些代码片段。首选构建一个总数 32 个数据项的表格模型,然后将其设置为一个表格视图的数据:

 
 
1
2
3
QTableWidget tableWidget(8, 4);
 
QItemSelectionModel *selectionModel = tableWidget.selectionModel();

在代码的最后,我们获得QTableView的选择模型,以备以后使用。

如今,我们没有改动模型中的数据。而是选择表格左上角的一些单元格。以下我们来看看代码怎样实现:

 
 
1
2
QModelIndex topLeft = tableWidget.model()->index(0, 0, QModelIndex());
QModelIndex bottomRight = tableWidget.model()->index(5, 2, QModelIndex());

接下来,我们将获得的两个索引定义为选区。

为达这一目的,我们首先构造一个QItemSelection对象,然后将其赋值给我们获取的选择模型:

 
 
1
2
QItemSelection selection(topLeft, bottomRight);
selectionModel->select(selection, QItemSelectionModel::Select);

正如前面我们说的。首先利用左上角和右下角的坐标构建一个QItemSelection对象,然后将这个对象设置为选择模型的选择区。

select()函数的第一个參数就是须要选择的选区,第二个參数是选区的标志位。

Qt
提供了非常多不同的操作,能够參考下QItemSelectionModel::SelectionFlags的文档。在本例中,我们使用了QItemSelectionModel::Select,这意味着选区中所包括的全部单元格都会被选择。

以下就是我们的执行结果:

如今我们知道怎样设置选区。以下来看看怎样获取选区。

获取选区须要使用selectedIndexes()函数。该函数返回一个无序列表。我们能够通过遍历这个列表获得哪些被选择:

 
 
1
2
3
4
5
6
7
QModelIndexList indexes = selectionModel->selectedIndexes();
QModelIndex index;
 
foreach(index, indexes) {
    QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
    model->setData(index, text);
}

在选择发生更改时。选择模型会发出信号。我们能够连接selectionChanged()信号,在选区改变时检查哪个项目发生了变化。这个信号有两个參数:第一个是新选择的项目。第二个是刚刚被取消选择的项目。

在以下的演示样例中。我们通过selectionChanged()信号,将全部新选择的项目填充字符串,将全部被取消选择的部分清空:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void MainWindow::updateSelection(const QItemSelection &selected,
                                 const QItemSelection &deselected)
{
    QModelIndex index;
    QModelIndexList items = selected.indexes();
 
    foreach (index, items) {
        QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
        model->setData(index, text);
    }
 
    items = deselected.indexes();
 
    foreach (index, items) {
        model->setData(index, "");
    }
}

通过currentChanged()。我们能够追踪当前有焦点的项。同selectionChanged()信号类似,这个信号也有两个參数:第一个是新的当前项,第二个是上一个当前项。

以下的代码则是该信号的使用:

 
 
1
2
3
4
5
6
7
8
void MainWindow::changeCurrent(const QModelIndex &current,
                               const QModelIndex &previous)
{
    statusBar()->showMessage(
        tr("Moved from (%1,%2) to (%3,%4)")
            .arg(previous.row()).arg(previous.column())
            .arg(current.row()).arg(current.column()));
}

这些信号能够用来监控选区的改变。假设你还要直接更新选区,我们还有另外的方法。

相同是利用前面所说的QItemSelectionModel::SelectionFlag,我们能够对选区进行组合操作。

还记得我们在前面的select()函数中使用过的第二个參数吗?当我们替换这个參数,就能够获得不同的组合方式。

最经常使用的就是QItemSelectionModel::Select,它的作用是将全部指定的选区都选择上。

QItemSelectionModel::Toggle则是一种取反的操作:假设指定的部分原来已经被选择,则取消选择,否则则选择上。

QItemSelectionModel::Deselect则是取消指定的已选择的部分。在以下的样例中。我们使用QItemSelectionModel::Toggle对前面的演示样例作进一步的操作:

 
 
1
2
3
4
5
6
7
QItemSelection toggleSelection;
 
topLeft = tableWidget.model()->index(2, 1, QModelIndex());
bottomRight = tableWidget.model()->index(7, 3, QModelIndex());
toggleSelection.select(topLeft, bottomRight);
 
selectionModel->select(toggleSelection, QItemSelectionModel::Toggle);

执行结果将例如以下所看到的:

默认情况下,选择操作会仅仅会影响到指定的模型索引。可是。我们也能够改变这一设置。比如,仅仅选择整行或者整列:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
QItemSelection columnSelection;
 
topLeft = model->index(0, 1, QModelIndex());
bottomRight = model->index(0, 2, QModelIndex());
 
columnSelection.select(topLeft, bottomRight);
 
selectionModel->select(columnSelection,
                       QItemSelectionModel::Select | QItemSelectionModel::Columns);
 
QItemSelection rowSelection;
 
topLeft = model->index(0, 0, QModelIndex());
bottomRight = model->index(1, 0, QModelIndex());
 
rowSelection.select(topLeft, bottomRight);
 
selectionModel->select(rowSelection,
                       QItemSelectionModel::Select | QItemSelectionModel::Rows);

上面的代码,我们依旧使用两个索引设置了一个区域。可是,在选择的使用我们使用了QItemSelectionModel::RowsQItemSelectionModel::Columns这两个參数。因此仅仅会选择这两个区域中指定的行或者列:

使用QItemSelectionModel::Current參数能够将当前选区替换为新的选区。使用QItemSelectionModel::Clear则会将原来已有的选区所有取消。为了进行全选。我们能够设置选区为左上角和右下角两个索引:

 
 
1
2
3
4
5
6
QModelIndex topLeft = model->index(0, 0, parent);
QModelIndex bottomRight = model->index(model->rowCount(parent)-1,
model->columnCount(parent)-1, parent);
 
QItemSelection selection(topLeft, bottomRight);
selectionModel->select(selection, QItemSelectionModel::Select);

Qt 学习: 视图选择 (QItemSelectionModel)的更多相关文章

  1. Qt 学习之路:视图选择 (QItemSelectionModel)

    选择是视图中常用的一个操作.在列表.树或者表格中,通过鼠标点击可以选中某一项,被选中项会变成高亮或者反色.在 Qt 中,选择也是使用了一种模型.在 model/view 架构中,这种选择模型提供了一种 ...

  2. Qt 学习之路 2(47):视图选择

    Qt 学习之路 2(47):视图选择 豆子 2013年3月28日 Qt 学习之路 2 34条评论 选择是视图中常用的一个操作.在列表.树或者表格中,通过鼠标点击可以选中某一项,被选中项会变成高亮或者反 ...

  3. Qt 学习之路 2(46):视图和委托

    Home / Qt 学习之路 2 / Qt 学习之路 2(46):视图和委托 Qt 学习之路 2(46):视图和委托  豆子  2013年3月11日  Qt 学习之路 2  63条评论 前面我们介绍了 ...

  4. PyQt(Python+Qt)学习随笔:视图中的拖放操作注意事项

    老猿Python博文目录 老猿Python博客地址 在通过PyQt构建的图形界面中进行拖放,要成功进行拖放需要注意: 视图相关属性需要支持拖放,具体相关属性请参考<PyQt(Python+Qt) ...

  5. PyQt(Python+Qt)学习随笔:视图中类QAbstractItemView的dragDropOverwriteMode属性不能覆盖写的问题

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在<PyQt(Python+Qt)学习随笔:视图中类QAbstractItemView的dra ...

  6. PyQt(Python+Qt)学习随笔:视图中类QAbstractItemView的dragDropOverwriteMode属性

    老猿Python博文目录 老猿Python博客地址 一.属性的作用 dragDropOverwriteMode属性用于控制视图的拖放行为,如果其值为True,则视图中选定的数据将在拖拽数据放下时被覆盖 ...

  7. PyQt(Python+Qt)学习随笔:视图中的dragDropMode属性对dragEnabled和acceptDrops属性的影响

    老猿Python博文目录 老猿Python博客地址 在<PyQt(Python+Qt)学习随笔:QAbstractItemView的dragEnabled和dragDropMode属性的关系&g ...

  8. QT学习教程

    原地址:http://www.devbean.NET/2012/08/qt-study-road-2-catelog/ 网上看到的不错的教程 本教程以qt5为主,部分地方会涉及qt4.据说非常适合qt ...

  9. Qt 模型/视图/委托

    模型.视图.委托 模型/视图架构基于MVC设计模式发展而来.MVC中,模型(Model)用来表示数据:视图(View)是界面,用来显示数据:控制(Controller)定义界面对用户输入的反应方式. ...

随机推荐

  1. IOIOI卡片占卜(Atcoder-IOIOI カード占い)(最短路)

    题目描述: K 理事長は占いが好きで,いつも様々な占いをしている.今日は,表の面に ‘I’ が,裏の面に ‘O’ が書か れたカードを使って今年の IOI での日本選手団の出来を占うことにした. 占い ...

  2. DTU(用于将串口数据转换为IP数据或将IP数据转换为串口数据通过无线通信网络进行传送的无线终端设备)

    DTU (Data Transfer unit),是专门用于将串口数据转换为IP数据或将IP数据转换为串口数据通过无线通信网络进行传送的无线终端设备.DTU广泛应用于气象.水文水利.地质等行业.

  3. bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式)

    bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式) 一.总结 一句话总结:通过监听滚动的高,判断滚动的高是否大于元素距离顶端的距离 1.如何知道屏幕滚动的高? st=$ ...

  4. Python的主成分分析PCA算法

    这篇文章很不错:https://blog.csdn.net/u013082989/article/details/53792010 为什么数据处理之前要进行归一化???(这个一直不明白) 这个也很不错 ...

  5. React组件之间通过Props传值的技巧(小案例,帮助体会理解props、state、受控组件和非受控组件等)

    本文重要是根据react小书上的一个很简单的例子改编的,加上自己的学习理解,希望可以通过实际案例让大家对概念有更清晰的理解,当然也希望能一块学习. import React,{Component} f ...

  6. IDEACould not autowire. No beans of 'xxxMapper' type found.

    作为一名刚开始使用idea的新手,最近在使用maven+springMVC框架时遇到了这样一个问题:Could not autowire. No beans of 'xxxMapper' type f ...

  7. 像Bootstrap一样比较热门的前端框架有哪些

    像Bootstrap一样比较热门的前端框架有哪些 一.总结 一句话总结:框架大同小异,可以多去各自官网看看效果(比较一下各自的不同点(也就是提供的不同的功能)),然后根据需求选择用哪个.我觉得boot ...

  8. 4、C++快速入门2

    1.抽象类 如果一个类里面有纯虚函数,其被编译器认为是一个抽象类,抽象类不能用来实例化一个对象 纯虚函数定义:virtual void 函数名(void)=  0; 抽象类是给派生类定义好接口函数,如 ...

  9. 【Codeforces Round #440 (Div. 2) A】 Search for Pretty Integers

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先枚举一个数字的情况. 再枚举两个数的情况就好. [代码] #include <bits/stdc++.h> #defi ...

  10. [Nuxt] Load Data from APIs with Nuxt and Vuex

    In a server-rendered application, if you attempt to load data before the page renders and the data f ...