实施钻取
注: 这是 "带小部件的图表图库"示例的一部分。
在这里,我们创建了一个堆叠条形图,显示各种辣椒在不同季节的收成情况。在季节视图中,收成按月分组。要深入查看周视图,请右键单击所选月份。在周视图中,点击月份的收成按周显示。
季节视图如下所示:
单击月份显示该月的收成:
首先,我们定义了一个钻取系列类,它可以为堆叠条形图系列添加类别,并将类别映射到其他钻取系列。下钻系列的目的是包含下钻结构的知识。mapDrilldownSeries 函数将类别映射到给定的系列。我们可以使用 drilldownSeries(int category) 函数请求类别的映射。
class StackedDrilldownSeries : public QStackedBarSeries { Q_OBJECT public: StackedDrilldownSeries(const QStringList &categories, int maxValue, QObject *parent = nullptr); void mapDrilldownSeries(int index, StackedDrilldownSeries *drilldownSeries); StackedDrilldownSeries *drilldownSeries(int index) const; QStringList categories() const; int maxValue() const; private: QMap<int, StackedDrilldownSeries *> m_drilldownSeries; QStringList m_categories; int m_maxValue = 0; };
接下来,我们定义自己的下钻图表,它实现了鼠标点击的处理程序。当鼠标点击一个系列时,所有QBarSeries 派生类都会发出 clicked(QBarSet*, int) 信号。参数QBarSet 包含指向被点击条集的指针,参数 int 包含被点击类别的索引。
class StackedDrilldownChart : public QChart { Q_OBJECT public: explicit StackedDrilldownChart(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {}); void changeSeries(StackedDrilldownSeries *series); public slots: void handleClicked(int index, QBarSet *); private: StackedDrilldownSeries *m_currentSeries = nullptr; QBarCategoryAxis *m_axisX = nullptr; QValueAxis *m_axisY = nullptr; };
现在我们有了下钻类,可以开始使用它们了。首先创建图表。
auto drilldownChart = new StackedDrilldownChart; drilldownChart->setAnimationOptions(QChart::SeriesAnimations);
我们要定义类别,并从中构建钻取系列。
// Define categories const QStringList months = { "May", "Jun", "Jul", "Aug", "Sep" }; const QStringList weeks = { "week 1", "week 2", "week 3", "week 4" }; const QStringList plants = { "Habanero", "Lemon Drop", "Starfish", "Aji Amarillo" };
为创建下拉结构,我们首先创建顶层系列,并将其称为 seasonSeries。对于 seasonSeries 中的每个月,我们都要创建一个名为 weeklySeries 的下拉序列,其中包含该月更详细的数据。在 weeklySeries 中,我们使用下拉处理程序来返回 seasonSeries。为此,我们为系列添加了映射。每个月的 seasonSeries 都会映射到 weeklySeries。每个周序列都会映射回季节序列。为了实现映射,我们将系列的点击信号连接到钻取图表。
// Create drilldown structure auto seasonSeries = new StackedDrilldownSeries(months, 320, drilldownChart); seasonSeries->setName("Crop by month - Season (Click on bar to drill down)"); // Each month in season series has drilldown series for weekly data for (int month = 0; month < months.count(); month++) { // Create drilldown series for every week auto weeklySeries = new StackedDrilldownSeries(weeks, 80, drilldownChart); seasonSeries->mapDrilldownSeries(month, weeklySeries); // Drilling down from weekly data brings us back to season data. for (int week = 0; week < weeks.count(); week++) { weeklySeries->mapDrilldownSeries(week, seasonSeries); weeklySeries->setName(QString("Crop by week - " + months.at(month))); } // Use clicked signal to implement drilldown QObject::connect(weeklySeries, &StackedDrilldownSeries::clicked, drilldownChart, &StackedDrilldownChart::handleClicked); } // Enable drilldown from season series using clicked signal QObject::connect(seasonSeries, &StackedDrilldownSeries::clicked, drilldownChart, &StackedDrilldownChart::handleClicked);
当我们准备好钻取结构后,就可以向其中添加数据了。在这里,我们为每周的每株植物随机生成一个作物。每月的收成由每周的收成计算得出,并将其设置为月度序列的值。
// Fill monthly and weekly series with data for (const QString &plant : plants) { auto monthlyCrop = new QBarSet(plant); for (int month = 0; month < months.count(); month++) { auto weeklyCrop = new QBarSet(plant); for (int week = 0; week < weeks.count(); week++) *weeklyCrop << QRandomGenerator::global()->bounded(20); // Get the drilldown series from season series and add crop to it. seasonSeries->drilldownSeries(month)->append(weeklyCrop); *monthlyCrop << weeklyCrop->sum(); } seasonSeries->append(monthlyCrop); }
在这里,我们将图表设置为显示顶层序列。
// Show season series in initial view drilldownChart->changeSeries(seasonSeries); drilldownChart->setTitle(seasonSeries->name());
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.