diff --git a/example/dynamiclinechart/main.cpp b/example/dynamiclinechart/main.cpp index 33c2dd7..ba1f727 100644 --- a/example/dynamiclinechart/main.cpp +++ b/example/dynamiclinechart/main.cpp @@ -28,6 +28,7 @@ int main(int argc, char *argv[]) chartView->setViewport( new QGLWidget() ); chartView->setRenderHint(QPainter::Antialiasing); + chartView->setAnimationOptions(QChart::AllAnimations); chartView->setChartTitle("This is wave generator buahha."); chartView->addSeries(series0); chartView->addSeries(series1); diff --git a/example/presenterchart/main.cpp b/example/presenterchart/main.cpp index fe739c7..17000f0 100644 --- a/example/presenterchart/main.cpp +++ b/example/presenterchart/main.cpp @@ -9,6 +9,7 @@ int main(int argc, char *argv[]) ChartView chartView(&window); chartView.setRenderHint(QPainter::Antialiasing); chartView.setChartTitle("Three random line charts"); + chartView.setAnimationOptions(QChart::AllAnimations); window.setCentralWidget(&chartView); window.resize(400, 300); window.show(); diff --git a/src/linechart/linechartanimationitem.cpp b/src/linechart/linechartanimationitem.cpp index 61f5501..0f67dc5 100644 --- a/src/linechart/linechartanimationitem.cpp +++ b/src/linechart/linechartanimationitem.cpp @@ -1,78 +1,77 @@ #include "linechartanimationitem_p.h" #include "linechartitem_p.h" #include +#include + +Q_DECLARE_METATYPE(QVector) QTCOMMERCIALCHART_BEGIN_NAMESPACE const static int duration = 500; - LineChartAnimationItem::LineChartAnimationItem(ChartPresenter* presenter, QLineSeries* series,QGraphicsItem *parent): -LineChartItem(presenter,series,parent) +LineChartItem(presenter,series,parent), +m_animation(new LineChartAnimatator(this,this)), +m_dirty(false) { - } LineChartAnimationItem::~LineChartAnimationItem() { } -void LineChartAnimationItem::addPoints(const QVector& points) +void LineChartAnimationItem::updateItem(QVector& oldPoints,QVector& newPoints) { - QVector vector0 = vector1; - calculateLayout(vector1); - if(vector1.count()==0) return; - vector0.resize(vector1.size()); - - - LineChartAnimatator *animation = new LineChartAnimatator(this,this); - animation->setDuration(duration); - animation->setEasingCurve(QEasingCurve::InOutBack); - animation->setKeyValueAt(0.0, qVariantFromValue(vector0)); - animation->setKeyValueAt(1.0, qVariantFromValue(vector1)); - animation->start(QAbstractAnimation::DeleteWhenStopped); - - QPropertyAnimation *animation = new QPropertyAnimation(this, "a_addPoints", parent()); - animation->setDuration(duration); - //animation->setEasingCurve(QEasingCurve::InOutBack); - animation->setKeyValueAt(0.0, 0); - animation->setKeyValueAt(1.0, m_data.size()); - animation->start(QAbstractAnimation::DeleteWhenStopped); -} + if(newPoints.count()==0) return; + oldPoints.resize(newPoints.size()); -void LineChartAnimationItem::replacePoint(int index,const QPointF& point) -{ - AnimationHelper* helper = new AnimationHelper(this,index); - QPropertyAnimation *animation = new QPropertyAnimation(helper, "point", parent()); - animation->setDuration(duration); - //animation->setEasingCurve(QEasingCurve::InOutBack); - animation->setKeyValueAt(0.0, points().value(index)); - animation->setKeyValueAt(1.0, point); - animation->start(QAbstractAnimation::DeleteWhenStopped); + if(m_animation->state()!=QAbstractAnimation::Stopped){ + m_animation->stop(); + } + + m_animation->setDuration(duration); + m_animation->setEasingCurve(QEasingCurve::InOutBack); + m_animation->setKeyValueAt(0.0, qVariantFromValue(oldPoints)); + m_animation->setKeyValueAt(1.0, qVariantFromValue(newPoints)); + QTimer::singleShot(0,m_animation,SLOT(start())); + + oldPoints = newPoints; + m_points = newPoints; + m_dirty=false; } -void LineChartAnimationItem::aw_addPoints(int points) +void LineChartAnimationItem::updateItem(QVector& oldPoints,int index,QPointF& newPoint) { - int index = count(); - for(int i = index;i< points ;i++){ - LineChartItem::addPoint(m_data.at(i)); + if(m_animation->state()!=QAbstractAnimation::Stopped){ + m_animation->stop(); + m_dirty=true; } - updateGeometry(); - update(); + + if(m_dirty){ + m_points=oldPoints; + m_dirty=false; + } + + oldPoints.replace(index,newPoint); + + m_animation->setDuration(duration); + m_animation->setEasingCurve(QEasingCurve::InOutBack); + m_animation->setKeyValueAt(0.0, qVariantFromValue(m_points)); + m_animation->setKeyValueAt(1.0, qVariantFromValue(oldPoints)); + QTimer::singleShot(0,this,SLOT(startAnimation())); + } -void LineChartAnimationItem::aw_setPoint(int index,const QPointF& point) +void LineChartAnimationItem::startAnimation() { - LineChartItem::replacePoint(index,point); - updateGeometry(); - update(); + m_dirty=true; + m_animation->start(); } -LineChartAnimatator::LineChartAnimatator(LineChartItem *item, int index , QObject *parent = 0 ):QVariantAnimation(parent), - m_item(item), - m_index(index) +LineChartAnimatator::LineChartAnimatator(LineChartAnimationItem *item , QObject *parent):QVariantAnimation(parent), + m_item(item) { -}; +} LineChartAnimatator::~LineChartAnimatator() { @@ -80,26 +79,25 @@ LineChartAnimatator::~LineChartAnimatator() QVariant LineChartAnimatator::interpolated(const QVariant &start, const QVariant & end, qreal progress ) const { - QVector startVector = qVariantValue >(start); - QVector endVecotr = qVariantValue >(end); - QVector result; + QVector startVector = qVariantValue >(start); + QVector endVecotr = qVariantValue >(end); + QVector result; Q_ASSERT(startVector.count() == endVecotr.count()); for(int i =0 ;i< startVector.count();i++){ - qreal value = startVector[i] + ((endVecotr[i]- startVector[i]) * progress);//qBound(0.0, progress, 1.0)); - result << value; + qreal x = startVector[i].x() + ((endVecotr[i].x()- startVector[i].x()) * progress);//qBound(0.0, progress, 1.0)); + qreal y = startVector[i].y() + ((endVecotr[i].y()- startVector[i].y()) * progress);//qBound(0.0, progress, 1.0)); + result << QPointF(x,y); } return qVariantFromValue(result); } - void LineChartAnimatator::updateCurrentValue (const QVariant & value ) { - QVector vector = qVariantValue >(value); - m_axis->applyLayout(vector); + QVector vector = qVariantValue >(value); + m_item->applyGeometry(vector); } - #include "moc_linechartanimationitem_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/linechart/linechartanimationitem_p.h b/src/linechart/linechartanimationitem_p.h index eef325e..188f5c3 100644 --- a/src/linechart/linechartanimationitem_p.h +++ b/src/linechart/linechartanimationitem_p.h @@ -4,37 +4,45 @@ #include "qchartglobal.h" #include "linechartitem_p.h" #include "domain_p.h" +#include QTCOMMERCIALCHART_BEGIN_NAMESPACE -class LineChartItem; +class LineChartAnimatator; class LineChartAnimationItem : public LineChartItem { + Q_OBJECT + public: LineChartAnimationItem(ChartPresenter* presenter, QLineSeries *series, QGraphicsItem *parent = 0); virtual ~LineChartAnimationItem(); - void addPoints(const QVector& points); - void replacePoint(int index,const QPointF& point); +protected: + virtual void updateItem(QVector& oldPoints,QVector& newPoints); + virtual void updateItem(QVector& oldPoints,int index,QPointF& newPoint); + +private slots: + void startAnimation(); private: - QVector m_data; - Domain m_domain; - int m_addPoints; - QPointF m_setPoint; - int m_setPoint_index; + LineChartAnimatator *m_animation; + QVector m_points; + bool m_dirty; }; class LineChartAnimatator: public QVariantAnimation { - public: - LineChartAnimatator(LineChartItem *item, int index , QObject *parent = 0 ):m_item(item),m_index(index){}; + LineChartAnimatator(LineChartAnimationItem *item, QObject *parent = 0 ); + ~LineChartAnimatator(); - QPointF m_point; +protected: + QVariant interpolated(const QVariant &start, const QVariant & end, qreal progress ) const; + void updateCurrentValue (const QVariant & value ); + +private: LineChartAnimationItem* m_item; - int m_index; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp index 24e3a12..8abbf00 100644 --- a/src/linechart/linechartitem.cpp +++ b/src/linechart/linechartitem.cpp @@ -6,12 +6,14 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -//TODO: optimazie : remove points which are not visible +//TODO: optimize : remove points which are not visible LineChartItem::LineChartItem(ChartPresenter* presenter, QLineSeries* series,QGraphicsItem *parent):ChartItem(parent), m_presenter(presenter), -m_series(series) +m_series(series), +m_items(this) { + //m_items.setZValue(ChartPresenter::LineChartZValue); setZValue(ChartPresenter::LineChartZValue); } @@ -28,7 +30,7 @@ QPainterPath LineChartItem::shape() const void LineChartItem::createPoints(int count) { for (int i = 0; i < count; ++i) { - QGraphicsRectItem* item = new QGraphicsRectItem(0,0,3,3,this); + QGraphicsRectItem* item = new QGraphicsRectItem(0,0,3,3); m_items.addToGroup(item); } } @@ -42,18 +44,7 @@ void LineChartItem::clearPoints(int count) } } -void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(widget); - Q_UNUSED(option); - painter->save(); - painter->setPen(m_pen); - painter->setClipRect(m_clipRect); - painter->drawPath(m_path); - painter->restore(); -} - -QPointF LineChartItem::calculatePoint(int index) const +QPointF LineChartItem::calculateGeometryPoint(int index) const { const qreal deltaX = m_size.width()/m_domain.spanX(); const qreal deltaY = m_size.height()/m_domain.spanY(); @@ -62,34 +53,31 @@ QPointF LineChartItem::calculatePoint(int index) const return QPointF(x,y); } - -void LineChartItem::calculatePoints(QVector& points, QVector& map) const +QVector LineChartItem::calculateGeometryPoints() const { const qreal deltaX = m_size.width()/m_domain.spanX(); const qreal deltaY = m_size.height()/m_domain.spanY(); + QVector points; + points.reserve(m_series->count()); for (int i = 0; i < m_series->count(); ++i) { qreal x = (m_series->x(i) - m_domain.m_minX)* deltaX; qreal y = (m_series->y(i) - m_domain.m_minY)*-deltaY + m_size.height(); - map << i; points << QPointF(x,y); } + return points; } -void LineChartItem::updateItem(QVector& points,QVector& map) +void LineChartItem::updateItem(QVector& oldPoints,QVector& newPoints) { - int diff = m_points.size() - points.size(); - - if(diff>0) { - clearPoints(diff); - } - else if(diff<0) { - createPoints(-diff); - } + applyGeometry(newPoints); + oldPoints = newPoints; +} - applyGeometry(points); - m_points=points; - m_map=map; +void LineChartItem::updateItem(QVector& oldPoints,int index,QPointF& newPoint) +{ + oldPoints.replace(index,newPoint); + applyGeometry(oldPoints); } void LineChartItem::applyGeometry(QVector& points) @@ -103,6 +91,7 @@ void LineChartItem::applyGeometry(QVector& points) path.moveTo(point); QGraphicsItem* item = items.at(0); item->setPos(point.x()-1,point.y()-1); + if(!m_clipRect.contains(point)) item->setVisible(false); for(int i=1 ; i< points.size();i++) { QGraphicsItem* item = items.at(i); @@ -129,104 +118,79 @@ void LineChartItem::handlePointAdded(int index) Q_ASSERT(indexcount()); Q_ASSERT(index>=0); - if(m_map.contains(index)){ - - int i = m_map.indexOf(index); - - QPointF point = calculatePoint(index); - - if(point.isNull()) return; - - QVector points = m_points; - points.insert(i,point); - - for(int j=i;j points = m_points; + points.insert(index,point); + updateItem(m_points,points); + update(); } void LineChartItem::handlePointRemoved(int index) { Q_ASSERT(indexcount()); Q_ASSERT(index>=0); - - if(m_map.contains(index)){ - - int i = m_map.value(index); - - QVector points = m_points; - points.remove(i); - - for(int j=i;j points = m_points; + points.remove(index); + updateItem(m_points,points); + update(); } void LineChartItem::handlePointReplaced(int index) { Q_ASSERT(indexcount()); Q_ASSERT(index>=0); - - if(m_map.contains(index)){ - - int i = m_map.indexOf(index); - - QPointF point = calculatePoint(index); - - QVector points = m_points; - points.replace(i,point); - - updateItem(points,m_map); - - }else{ - //ignore - return; - } + QPointF point = calculateGeometryPoint(index); + updateItem(m_points,index,point); update(); } void LineChartItem::handleDomainChanged(const Domain& domain) { + m_domain = domain; + if(m_domain.isEmpty()) return; + if(!m_clipRect.isValid()) return; - QVector points; - QVector map; - calculatePoints(points,map); - updateItem(points,map); + QVector points = calculateGeometryPoints(); + + int diff = m_points.size() - points.size(); + + if(diff>0) { + clearPoints(diff); + } + else if(diff<0) { + createPoints(-diff); + } + + updateItem(m_points,points); update(); } void LineChartItem::handleGeometryChanged(const QRectF& rect) { - Q_ASSERT(rect.isValid()); - m_size=rect.size(); - m_clipRect=rect.translated(-rect.topLeft()); - setPos(rect.topLeft()); + Q_ASSERT(rect.isValid()); + m_size=rect.size(); + m_clipRect=rect.translated(-rect.topLeft()); + setPos(rect.topLeft()); - if(m_domain.isEmpty()) return; - if(m_points.isEmpty()) return; + if(m_domain.isEmpty()) return; - QVector points; - QVector map; - calculatePoints(points,map); - updateItem(points,map); - update(); + QVector points = calculateGeometryPoints(); + + int diff = m_points.size() - points.size(); + + if(diff>0) { + clearPoints(diff); + } + else if(diff<0) { + createPoints(-diff); + } + + updateItem(m_points,points); + update(); } void LineChartItem::handleSeriesUpdated() @@ -238,6 +202,19 @@ void LineChartItem::handleSeriesUpdated() update(); } +//painter + +void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + Q_UNUSED(option); + painter->save(); + painter->setPen(m_pen); + painter->setClipRect(m_clipRect); + painter->drawPath(m_path); + painter->restore(); +} + #include "moc_linechartitem_p.cpp" diff --git a/src/linechart/linechartitem_p.h b/src/linechart/linechartitem_p.h index ee08228..affb6a0 100644 --- a/src/linechart/linechartitem_p.h +++ b/src/linechart/linechartitem_p.h @@ -29,22 +29,18 @@ public slots: void handlePointAdded(int index); void handlePointRemoved(int index); void handlePointReplaced(int index); + void handleSeriesUpdated(); void handleDomainChanged(const Domain& domain); void handleGeometryChanged(const QRectF& size); -protected: - virtual void addPoint(const QPointF& ); - virtual void addPoints(const QVector& points); - virtual void removePoint(const QPointF& point); - virtual void replacePoint(const QPointF& oldPoint, const QPointF& newPoint); - virtual void replacePoint(int index,const QPointF& point); - virtual void updateItem(QVector& points,QVector& map); - virtual void applyGeometry(QVector& points); - - void clear(); - - QPointF calculatePoint(int index) const; - void calculatePoints(QVector& points,QVector& map) const; +public: + virtual void updateItem(QVector& oldPoints,QVector& newPoints); + virtual void updateItem(QVector& oldPoints,int index,QPointF& newPoint); + void applyGeometry(QVector& points); + void createPoints(int count); + void clearPoints(int count); + QPointF calculateGeometryPoint(int index) const; + QVector calculateGeometryPoints() const; private: ChartPresenter* m_presenter; @@ -53,9 +49,8 @@ private: QRectF m_rect; QRectF m_clipRect; Domain m_domain; - QList m_items; + QGraphicsItemGroup m_items; QVector m_points; - QVector m_map; QLineSeries* m_series; QPen m_pen;