Qt 图形 3D 数据处理
系列
一个系列集成了一个逻辑上相连的数据项集合和视觉属性,以描述数据项应该如何渲染,例如项网格和颜色。每种图形类型都有自己的系列类型。例如,条形图使用 QBar3DSeries。所有图形可以同时添加多个系列。每个系列都拥有自己的数据。
此代码片段展示了如何使用 QBar3DSeries 将条形渲染为圆柱形,而不是使用均匀的颜色
Q3DBars graph; QBar3DSeries *series = new QBar3DSeries; QLinearGradient barGradient(0, 0, 1, 100); barGradient.setColorAt(1.0, Qt::white); barGradient.setColorAt(0.0, Qt::black); series->setBaseGradient(barGradient); series->setColorStyle(Q3DTheme::ColorStyle::ObjectGradient); series->setMesh(QAbstract3DSeries::Mesh::Cylinder); graph.addSeries(series);
数据代理
用户希望可视化的数据来自许多不同的格式,所有这些格式都不能直接支持。因此,Qt 图形实现了数据代理,用户可以将数据以已知格式输入其中。每个图形在其系列中都有基本代理类型,它接受适合该图形的格式并可以直接由系列使用。
例如,QBar3DSeries 的基本代理是 QBarDataProxy,它用于将数据作为 QBarDataItem 对象添加到系列中。每个 QBarDataItem 包含一个单个条形值。还提供了对 QBarDataArray 和 QBarDataRow 容器的额外类型定义。
此代码片段展示了如何在使用假设的 myData
对象时使用基本代理,该对象以 QBarDataItems 形式返回数据
Q3DBars graph; QBar3DSeries *series = new QBar3DSeries; for (int i = 0; i < 10; ++i) { QBarDataRow dataRow; for (int j = 0; j < 5; ++j) dataRow.append(myData->getValue(i, j)); series->dataProxy()->addRow(dataRow); } graph.addSeries(series);
注意:系列对象一次只能拥有一个代理。当将另一个代理设置到系列中时,现有的代理将被删除。虽然图形可以包含多个系列,但如果需要在两组不同的数据之间切换,通常将每组数据存储在不同的系列中,并只更改系列会更有效率,而不是每次需要切换时都使用代理重置系列中的数据。
项模型和数据映射
对于常见用例,Qt 图形提供了专门的代理。其中一种情况是数据在项模型(QAbstractItemModel 子类)中,这是在 Qt 应用的常见数据存储方式。每种图形类型都为此目的提供了特殊代理类,例如,为 QBar3DSeries 提供了 QItemModelBarDataProxy。这些代理易于使用:将数据包含项模型的指针给它们,以及如何将数据映射成基本代理可以处理的格式的规则。
映射与项目模型角色协同工作。模型中的每个数据项可以根据不同的角色具有不同的值。例如,使用QItemModelBarDataProxy,您可以指定用于确定项目属于哪一行的角色,用于列的角色,以及指定项目值的角色。当代理从模型中解析数据时,它使用这些映射来生成条形图行和列。
通常,项目模型将有一个包含您想映射到多个值的单个角色的信息。一个典型的例子是在生成包含两个与时间相关的轴(例如年份和月份)的条形图时的时间戳字段。为了将单个项目模型角色映射到多个数据字段,项目模型代理提供了模式匹配和替换机制。您也可以使用此机制在一对一映射的情况下重新格式化数据。
根据图表的类型,代理可能还支持其他功能,例如,QItemModelBarDataProxy可选地将QAbstractItemModel的行和列直接映射到条形图行和列。
有关如何使用这些代理的更多信息,请参阅单独的代理类:QItemModelBarDataProxy,QItemModelScatterDataProxy和QItemModelSurfaceDataProxy。
其他自定义代理
QHeightMapSurfaceDataProxy是一种用于从高度图图像生成表面图的专用代理。有关更多详细信息,请参阅QHeightMapSurfaceDataProxy文档。
在条形图选项卡下,示例Graph Gallery显示如何创建自定义代理。它定义了一个基于变量列表的自定义数据集,并扩展了基本代理以与关联的映射器解析该数据。
处理实时数据
当您有快速更新的数据集时,正确处理数据非常重要,以确保良好的性能。由于内存分配是一项昂贵的操作,始终在可能的情况下使用QList::reserve()和QList::resize()来避免在构建要提供给代理的数组时进行不必要的重新分配。如果需要为每一帧更改整个数据集,在大多数情况下最好重用现有数组,特别是如果数组维度没有改变。如果您需要在每一帧中添加、插入、删除或更改多个行或项目,始终通过单一方法调用来执行,比影响每个行或项目的多个调用更有效。例如,使用单个QBarDataProxy::addRows()调用添加十个行要比分十个QBarDataProxy::addRow()调用更有效率。
由于Bars3D
已针对只访问在数据窗口内的数据进行优化,因此即使在通过代理不断向系列添加更多数据时,不会出现明显的减慢。
由于散点数据是无序的,因此数据窗口范围中的任何更改都需要检查所有数据点是否可见,这可能导致在持续向代理添加数据时出现逐渐减慢。为了获得最佳性能,在代理中仅保留所需的数据。
虽然从项目级来看表面数据与散点数据类似,但它已经被分配到行和列中,因此表面渲染器可以通过假设行和列中的数据分别沿各自轴排序来优化绘图。它不如条形图那样高效,但几乎一样。
© 2024 Qt公司有限公司。此处包含的文档贡献是各自拥有者的著作权。提供的文档依照自由软件基金会发布的条款,使用GNU自由文档许可证版本1.3许可。Qt及其相关标志是芬兰及/或其他全球国家的商标,由Qt公司持有。其他所有商标均属于各自所有者。