diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2016-08-26 15:53:02 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2016-09-19 10:51:01 +0000 |
commit | 105d75533d31ceee0c39ef9e084294ed49ecbd89 (patch) | |
tree | 4d2a73a1974d8ccd79d027ab19f8d4143909b458 /src/charts/barchart/vertical/percent | |
parent | ced3a47d266938fd73a4b45f56cca4847cbb6967 (diff) |
Optimize barcharts painting
Previously, bar charts used to recreate the bar chart visuals from
scratch whenever any change to the bar data occurred.
The following changes were made:
- Graphics items are generated only for visible bars and labels
- Graphics items are reused if layout or data changes
- Labels are not generated unless they are visible
- Only newly added bars are animated from scratch; existing bars
will retain their size, making things more visually pleasing.
With these optimizations, the size of the bar series is irrelevant
to the painting performance, only thing that matters is how many
bars and labels are actually within visible range.
Task-number: QTBUG-52442
Change-Id: If3199a86e6819ef6219d2eb5f06d729c0bdbd2ae
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'src/charts/barchart/vertical/percent')
-rw-r--r-- | src/charts/barchart/vertical/percent/percentbarchartitem.cpp | 135 | ||||
-rw-r--r-- | src/charts/barchart/vertical/percent/percentbarchartitem_p.h | 5 |
2 files changed, 70 insertions, 70 deletions
diff --git a/src/charts/barchart/vertical/percent/percentbarchartitem.cpp b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp index 9f587448..2cd06f51 100644 --- a/src/charts/barchart/vertical/percent/percentbarchartitem.cpp +++ b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp @@ -38,56 +38,96 @@ QT_CHARTS_BEGIN_NAMESPACE PercentBarChartItem::PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) : AbstractBarChartItem(series, item) { + m_orientation = Qt::Vertical; connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)), this, SLOT(handleLabelsPositionChanged())); connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels())); } -void PercentBarChartItem::initializeLayout() +QString PercentBarChartItem::generateLabelText(int set, int category, qreal value) { - qreal categoryCount = m_series->d_func()->categoryCount(); - qreal setCount = m_series->count(); - qreal barWidth = m_series->d_func()->barWidth(); - - m_layout.clear(); - for(int category = 0; category < categoryCount; category++) { - for (int set = 0; set < setCount; set++) { - QRectF rect; - QPointF topLeft; - QPointF bottomRight; + Q_UNUSED(value) - if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData); - } else { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData); - } + static const QString valueTag(QLatin1String("@value")); + qreal p = m_series->d_func()->percentageAt(set, category) * 100.0; + QString vString(presenter()->numberToString(p, 'f', 0)); + QString valueLabel; + if (m_series->labelsFormat().isEmpty()) { + vString.append(QStringLiteral("%")); + valueLabel = vString; + } else { + valueLabel = m_series->labelsFormat(); + valueLabel.replace(valueTag, vString); + } - if (!m_validData) - return; + return valueLabel; +} +void PercentBarChartItem::initializeLayout(int set, int category, int layoutIndex, + bool resetAnimation) +{ + Q_UNUSED(set) + Q_UNUSED(resetAnimation) + + QRectF rect; + + int previousSetIndex = layoutIndex - m_categoryCount; + if (previousSetIndex >= 0) { + rect = m_layout.at(previousSetIndex); + rect.setBottom(rect.top()); + } else { + QPointF topLeft; + QPointF bottomRight; + qreal barWidth = m_series->d_func()->barWidth(); + if (domain()->type() == AbstractDomain::XLogYDomain + || domain()->type() == AbstractDomain::LogXLogYDomain) { + topLeft = domain()->calculateGeometryPoint( + QPointF(category - barWidth / 2, domain()->minY()), m_validData); + bottomRight = domain()->calculateGeometryPoint( + QPointF(category + barWidth / 2, domain()->minY()), m_validData); + } else { + topLeft = domain()->calculateGeometryPoint( + QPointF(category - barWidth / 2, 0), m_validData); + bottomRight = domain()->calculateGeometryPoint( + QPointF(category + barWidth / 2, 0), m_validData); + } + if (m_validData) { rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); - m_layout.append(rect.normalized()); } } + + m_layout[layoutIndex] = rect.normalized(); +} + +void PercentBarChartItem::markLabelsDirty(QBarSet *barset, int visualIndex, int count) +{ + Q_UNUSED(barset) + // Percent series need to dirty all labels of the stack + QList<QBarSet *> sets = m_barMap.keys(); + for (int set = 0; set < sets.size(); set++) + AbstractBarChartItem::markLabelsDirty(sets.at(set), visualIndex, count); } QVector<QRectF> PercentBarChartItem::calculateLayout() { QVector<QRectF> layout; + layout.reserve(m_layout.size()); // Use temporary qreals for accuracy - qreal categoryCount = m_series->d_func()->categoryCount(); qreal setCount = m_series->count(); qreal barWidth = m_series->d_func()->barWidth(); - for(int category = 0; category < categoryCount; category++) { - qreal sum = 0; - qreal categorySum = m_series->d_func()->categorySum(category); - for (int set = 0; set < setCount; set++) { - qreal value = m_series->barSets().at(set)->at(category); + QVector<qreal> categorySums(m_categoryCount); + QVector<qreal> tempSums(m_categoryCount, 0.0); + for (int category = 0; category < m_categoryCount; category++) + categorySums[category] = m_series->d_func()->categorySum(category + m_firstCategory); + for (int set = 0; set < setCount; set++) { + const QBarSet *barSet = m_series->barSets().at(set); + for (int category = m_firstCategory; category <= m_lastCategory; category++) { + qreal &sum = tempSums[category - m_firstCategory]; + const qreal &categorySum = categorySums.at(category - m_firstCategory); + qreal value = barSet->at(category); QRectF rect; qreal topY = 0; qreal newSum = value + sum; @@ -112,47 +152,6 @@ QVector<QRectF> PercentBarChartItem::calculateLayout() return layout; } -void PercentBarChartItem::handleUpdatedBars() -{ - // Handle changes in pen, brush, labels etc. - int categoryCount = m_series->d_func()->categoryCount(); - int setCount = m_series->count(); - int itemIndex(0); - static const QString valueTag(QLatin1String("@value")); - - for (int category = 0; category < categoryCount; category++) { - for (int set = 0; set < setCount; set++) { - QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data(); - Bar *bar = m_bars.at(itemIndex); - bar->setPen(barSet->m_pen); - bar->setBrush(barSet->m_brush); - bar->update(); - - QGraphicsTextItem *label = m_labels.at(itemIndex); - qreal p = m_series->d_func()->percentageAt(set, category) * 100.0; - QString vString(presenter()->numberToString(p, 'f', 0)); - QString valueLabel; - if (p == 0) { - label->setVisible(false); - } else { - label->setVisible(m_series->isLabelsVisible()); - if (m_series->labelsFormat().isEmpty()) { - vString.append(QStringLiteral("%")); - valueLabel = vString; - } else { - valueLabel = m_series->labelsFormat(); - valueLabel.replace(valueTag, vString); - } - } - label->setHtml(valueLabel); - label->setFont(barSet->m_labelFont); - label->setDefaultTextColor(barSet->m_labelBrush.color()); - label->update(); - itemIndex++; - } - } -} - void PercentBarChartItem::handleLabelsPositionChanged() { positionLabels(); diff --git a/src/charts/barchart/vertical/percent/percentbarchartitem_p.h b/src/charts/barchart/vertical/percent/percentbarchartitem_p.h index 3a248d07..c46697ef 100644 --- a/src/charts/barchart/vertical/percent/percentbarchartitem_p.h +++ b/src/charts/barchart/vertical/percent/percentbarchartitem_p.h @@ -52,7 +52,7 @@ class PercentBarChartItem : public AbstractBarChartItem Q_OBJECT public: PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item = 0); - void handleUpdatedBars(); + QString generateLabelText(int set, int category, qreal value); private Q_SLOTS: void handleLabelsPositionChanged(); @@ -60,7 +60,8 @@ private Q_SLOTS: private: virtual QVector<QRectF> calculateLayout(); - void initializeLayout(); + void initializeLayout(int set, int category, int layoutIndex, bool resetAnimation); + void markLabelsDirty(QBarSet *barset, int visualIndex, int count); }; QT_CHARTS_END_NAMESPACE |