实现信息钻取
注意:这是图表与小部件画廊示例Charts with Widgets Gallery的一部分。
在这里我们创建一个堆叠条形图,以展示整个季节各种辣椒的产量。在季节视图中,产量按月分组。要钻取到周视图,右键单击选定的月份。在周视图中,月份点击的产量以周为单位显示。
季节视图如下
单击月份将显示该月的收获
首先,我们定义一个钻取系列类,它将类别添加到堆叠条形系列,并为类别到其他钻取系列的映射。钻取系列的目的在于包含钻取结构的知识。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。每个weeklySeries都映射回seasonSeries。为了使映射工作,我们将系列的点击信号连接到钻取图表。
// 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());
© 2024 Qt 公司有限公司。此处包含的文档贡献归其各自的所有者所有。本处的文档是根据自由软件基金会发布的GNU 自由文档许可证版本 1.3的条款授权的。Qt和相应的徽标是芬兰和/或世界上其他国家的Qt公司有限公司的商标。所有其他商标均为其各自所有者的财产。