实现信息钻取

注意:这是图表与小部件画廊示例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公司有限公司的商标。所有其他商标均为其各自所有者的财产。