##// END OF EJS Templates
Fixed coordinate bug with QScatterSeries::onClicked
Tero Ahola -
r1410:41224d5421f7
parent child
Show More
@@ -1,60 +1,76
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartview.h"
21 #include "chartview.h"
22 #include <math.h>
23 #include <QDebug>
22
24
23 QTCOMMERCIALCHART_USE_NAMESPACE
25 QTCOMMERCIALCHART_USE_NAMESPACE
24
26
25 ChartView::ChartView(QWidget *parent)
27 ChartView::ChartView(QWidget *parent)
26 : QChartView(new QChart(), parent),
28 : QChartView(new QChart(), parent),
27 m_scatter(0),
29 m_scatter(0),
28 m_scatter2(0)
30 m_scatter2(0)
29 {
31 {
30 setRenderHint(QPainter::Antialiasing);
32 setRenderHint(QPainter::Antialiasing);
31
33
32 chart()->setTitle("Click to interact with scatter points");
34 chart()->setTitle("Click to interact with scatter points");
33
35
34 m_scatter = new QScatterSeries();
36 m_scatter = new QScatterSeries();
35 m_scatter->setName("scatter1");
37 m_scatter->setName("scatter1");
36 for(qreal x(0.5); x <= 4.0; x += 0.5) {
38 for(qreal x(0.5); x <= 4.0; x += 0.5) {
37 for(qreal y(0.5); y <= 4.0; y += 0.5) {
39 for(qreal y(0.5); y <= 4.0; y += 0.5) {
38 *m_scatter << QPointF(x, y);
40 *m_scatter << QPointF(x, y);
39 }
41 }
40 }
42 }
41 m_scatter2 = new QScatterSeries();
43 m_scatter2 = new QScatterSeries();
42 m_scatter2->setName("scatter2");
44 m_scatter2->setName("scatter2");
43
45
44 chart()->addSeries(m_scatter2);
46 chart()->addSeries(m_scatter2);
45 chart()->addSeries(m_scatter);
47 chart()->addSeries(m_scatter);
46 chart()->axisX()->setRange(0, 4.5);
48 chart()->axisX()->setRange(0, 4.5);
47 chart()->axisY()->setRange(0, 4.5);
49 chart()->axisY()->setRange(0, 4.5);
48
50
49 connect(m_scatter, SIGNAL(clicked(QPointF)), this, SLOT(handleClickedPoint(QPointF)));
51 connect(m_scatter, SIGNAL(clicked(QPointF)), this, SLOT(handleClickedPoint(QPointF)));
50 }
52 }
51
53
52 ChartView::~ChartView()
54 ChartView::~ChartView()
53 {
55 {
54 }
56 }
55
57
56 void ChartView::handleClickedPoint(const QPointF& point)
58 void ChartView::handleClickedPoint(const QPointF& point)
57 {
59 {
58 m_scatter->remove(point);
60 QPointF clickedPoint = point;
59 m_scatter2->append(point);
61 // Find the closest point from series 1
62 QPointF closest(INT64_MAX, INT64_MAX);
63 qreal distance(INT64_MAX);
64 foreach(QPointF currentPoint, m_scatter->points()) {
65 qreal currentDistance = sqrt((currentPoint.x() - clickedPoint.x()) * (currentPoint.x() - clickedPoint.x())
66 + (currentPoint.y() - clickedPoint.y()) * (currentPoint.y() - clickedPoint.y()));
67 if (currentDistance < distance) {
68 distance = currentDistance;
69 closest = currentPoint;
70 }
71 }
72
73 // Remove the closes point from series 1 and append it to series 2
74 m_scatter->remove(closest);
75 m_scatter2->append(closest);
60 }
76 }
@@ -1,207 +1,207
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "scatterchartitem_p.h"
21 #include "scatterchartitem_p.h"
22 #include "qscatterseries.h"
22 #include "qscatterseries.h"
23 #include "qscatterseries_p.h"
23 #include "qscatterseries_p.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include <QPainter>
25 #include <QPainter>
26 #include <QGraphicsScene>
26 #include <QGraphicsScene>
27 #include <QDebug>
27 #include <QDebug>
28 #include <QGraphicsSceneMouseEvent>
28 #include <QGraphicsSceneMouseEvent>
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 ScatterChartItem::ScatterChartItem(QScatterSeries *series, ChartPresenter *presenter) :
32 ScatterChartItem::ScatterChartItem(QScatterSeries *series, ChartPresenter *presenter) :
33 XYChart(series,presenter),
33 XYChart(series,presenter),
34 QGraphicsItem(presenter ? presenter->rootItem() : 0),
34 QGraphicsItem(presenter ? presenter->rootItem() : 0),
35 m_series(series),
35 m_series(series),
36 m_items(this),
36 m_items(this),
37 m_visible(true),
37 m_visible(true),
38 m_shape(QScatterSeries::MarkerShapeRectangle),
38 m_shape(QScatterSeries::MarkerShapeRectangle),
39 m_size(15)
39 m_size(15)
40 {
40 {
41 QObject::connect(m_series->d_func(),SIGNAL(updated()), this, SLOT(handleUpdated()));
41 QObject::connect(m_series->d_func(),SIGNAL(updated()), this, SLOT(handleUpdated()));
42 QObject::connect(m_series, SIGNAL(markerShapeChanged()), this, SLOT(handleUpdated()));
42 QObject::connect(m_series, SIGNAL(markerShapeChanged()), this, SLOT(handleUpdated()));
43 QObject::connect(m_series, SIGNAL(markerSizeChanged()), this, SLOT(handleUpdated()));
43 QObject::connect(m_series, SIGNAL(markerSizeChanged()), this, SLOT(handleUpdated()));
44 QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
44 QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
45
45
46 setZValue(ChartPresenter::ScatterSeriesZValue);
46 setZValue(ChartPresenter::ScatterSeriesZValue);
47 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
47 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
48
48
49 handleUpdated();
49 handleUpdated();
50
50
51 m_items.setHandlesChildEvents(false);
51 m_items.setHandlesChildEvents(false);
52
52
53 // TODO: how to draw a drop shadow?
53 // TODO: how to draw a drop shadow?
54 // QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect();
54 // QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect();
55 // dropShadow->setOffset(2.0);
55 // dropShadow->setOffset(2.0);
56 // dropShadow->setBlurRadius(2.0);
56 // dropShadow->setBlurRadius(2.0);
57 // setGraphicsEffect(dropShadow);
57 // setGraphicsEffect(dropShadow);
58 }
58 }
59
59
60 QRectF ScatterChartItem::boundingRect() const
60 QRectF ScatterChartItem::boundingRect() const
61 {
61 {
62 return m_rect;
62 return m_rect;
63 }
63 }
64
64
65 void ScatterChartItem::createPoints(int count)
65 void ScatterChartItem::createPoints(int count)
66 {
66 {
67 for (int i = 0; i < count; ++i) {
67 for (int i = 0; i < count; ++i) {
68
68
69 QGraphicsItem *item = 0;
69 QGraphicsItem *item = 0;
70
70
71 switch (m_shape) {
71 switch (m_shape) {
72 case QScatterSeries::MarkerShapeCircle: {
72 case QScatterSeries::MarkerShapeCircle: {
73 QGraphicsEllipseItem* i = new QGraphicsEllipseItem(0,0,m_size,m_size);
73 QGraphicsEllipseItem* i = new QGraphicsEllipseItem(0,0,m_size,m_size);
74 const QRectF& rect = i->boundingRect();
74 const QRectF& rect = i->boundingRect();
75 i->setPos(-rect.width()/2,-rect.height()/2);
75 i->setPos(-rect.width()/2,-rect.height()/2);
76 item = new Marker(i,this);
76 item = new Marker(i,this);
77 break;
77 break;
78 }
78 }
79 case QScatterSeries::MarkerShapeRectangle: {
79 case QScatterSeries::MarkerShapeRectangle: {
80 QGraphicsRectItem* i = new QGraphicsRectItem(0,0,m_size,m_size);
80 QGraphicsRectItem* i = new QGraphicsRectItem(0,0,m_size,m_size);
81 i->setPos(-m_size/2,-m_size/2);
81 i->setPos(-m_size/2,-m_size/2);
82 item = new Marker(i,this);
82 item = new Marker(i,this);
83 break;
83 break;
84 }
84 }
85 default:
85 default:
86 qWarning()<<"Unsupported marker type";
86 qWarning()<<"Unsupported marker type";
87 break;
87 break;
88
88
89 }
89 }
90 m_items.addToGroup(item);
90 m_items.addToGroup(item);
91 }
91 }
92 }
92 }
93
93
94 void ScatterChartItem::deletePoints(int count)
94 void ScatterChartItem::deletePoints(int count)
95 {
95 {
96 QList<QGraphicsItem *> items = m_items.childItems();
96 QList<QGraphicsItem *> items = m_items.childItems();
97
97
98 for (int i = 0; i < count; ++i) {
98 for (int i = 0; i < count; ++i) {
99 delete(items.takeLast());
99 delete(items.takeLast());
100 }
100 }
101 }
101 }
102
102
103 void ScatterChartItem::markerSelected(Marker *marker)
103 void ScatterChartItem::markerSelected(Marker *marker)
104 {
104 {
105 emit XYChart::clicked(marker->point());
105 emit XYChart::clicked(calculateDomainPoint(marker->point()));
106 }
106 }
107
107
108 void ScatterChartItem::updateGeometry()
108 void ScatterChartItem::updateGeometry()
109 {
109 {
110
110
111 const QVector<QPointF>& points = geometryPoints();
111 const QVector<QPointF>& points = geometryPoints();
112
112
113 if(points.size()==0)
113 if(points.size()==0)
114 {
114 {
115 deletePoints(m_items.childItems().count());
115 deletePoints(m_items.childItems().count());
116 return;
116 return;
117 }
117 }
118
118
119 int diff = m_items.childItems().size() - points.size();
119 int diff = m_items.childItems().size() - points.size();
120
120
121 if(diff>0) {
121 if(diff>0) {
122 deletePoints(diff);
122 deletePoints(diff);
123 }
123 }
124 else if(diff<0) {
124 else if(diff<0) {
125 createPoints(-diff);
125 createPoints(-diff);
126 }
126 }
127
127
128 if(diff!=0) handleUpdated();
128 if(diff!=0) handleUpdated();
129
129
130 QList<QGraphicsItem*> items = m_items.childItems();
130 QList<QGraphicsItem*> items = m_items.childItems();
131
131
132 for (int i = 0; i < points.size(); i++) {
132 for (int i = 0; i < points.size(); i++) {
133 Marker* item = static_cast<Marker*>(items.at(i));
133 Marker* item = static_cast<Marker*>(items.at(i));
134 const QPointF& point = points.at(i);
134 const QPointF& point = points.at(i);
135 const QRectF& rect = item->boundingRect();
135 const QRectF& rect = item->boundingRect();
136 item->setPoint(point);
136 item->setPoint(point);
137 item->setPos(point.x()-rect.width()/2,point.y()-rect.height()/2);
137 item->setPos(point.x()-rect.width()/2,point.y()-rect.height()/2);
138 if(!m_visible || !clipRect().contains(point)) {
138 if(!m_visible || !clipRect().contains(point)) {
139 item->setVisible(false);
139 item->setVisible(false);
140 }
140 }
141 else {
141 else {
142 item->setVisible(true);
142 item->setVisible(true);
143 }
143 }
144 }
144 }
145
145
146 prepareGeometryChange();
146 prepareGeometryChange();
147 m_rect = clipRect();
147 m_rect = clipRect();
148 setPos(origin());
148 setPos(origin());
149 }
149 }
150
150
151 void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
151 void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
152 {
152 {
153 Q_UNUSED(painter)
153 Q_UNUSED(painter)
154 Q_UNUSED(option)
154 Q_UNUSED(option)
155 Q_UNUSED(widget)
155 Q_UNUSED(widget)
156 }
156 }
157
157
158 void ScatterChartItem::setPen(const QPen& pen)
158 void ScatterChartItem::setPen(const QPen& pen)
159 {
159 {
160 foreach(QGraphicsItem* item , m_items.childItems()) {
160 foreach(QGraphicsItem* item , m_items.childItems()) {
161 static_cast<Marker*>(item)->setPen(pen);
161 static_cast<Marker*>(item)->setPen(pen);
162 }
162 }
163 }
163 }
164
164
165 void ScatterChartItem::setBrush(const QBrush& brush)
165 void ScatterChartItem::setBrush(const QBrush& brush)
166 {
166 {
167 foreach(QGraphicsItem* item , m_items.childItems()) {
167 foreach(QGraphicsItem* item , m_items.childItems()) {
168 static_cast<Marker*>(item)->setBrush(brush);
168 static_cast<Marker*>(item)->setBrush(brush);
169 }
169 }
170 }
170 }
171
171
172 void ScatterChartItem::handleUpdated()
172 void ScatterChartItem::handleUpdated()
173 {
173 {
174 int count = m_items.childItems().count();
174 int count = m_items.childItems().count();
175
175
176 if(count==0) return;
176 if(count==0) return;
177
177
178 bool recreate = m_visible != m_series->isVisible()
178 bool recreate = m_visible != m_series->isVisible()
179 || m_size != m_series->markerSize()
179 || m_size != m_series->markerSize()
180 || m_shape != m_series->markerShape();
180 || m_shape != m_series->markerShape();
181
181
182 m_visible = m_series->isVisible();
182 m_visible = m_series->isVisible();
183 m_size = m_series->markerSize();
183 m_size = m_series->markerSize();
184 m_shape = m_series->markerShape();
184 m_shape = m_series->markerShape();
185
185
186 if(recreate) {
186 if(recreate) {
187 // TODO: optimize handleUpdate to recreate points only in case shape changed
187 // TODO: optimize handleUpdate to recreate points only in case shape changed
188 deletePoints(count);
188 deletePoints(count);
189 createPoints(count);
189 createPoints(count);
190
190
191 // Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points
191 // Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points
192 updateGeometry();
192 updateGeometry();
193 }
193 }
194
194
195 setPen(m_series->pen());
195 setPen(m_series->pen());
196 setBrush(m_series->brush());
196 setBrush(m_series->brush());
197 update();
197 update();
198 }
198 }
199
199
200 void ScatterChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
200 void ScatterChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
201 {
201 {
202 emit XYChart::clicked(calculateDomainPoint(event->pos()));
202 emit XYChart::clicked(calculateDomainPoint(event->pos()));
203 }
203 }
204
204
205 #include "moc_scatterchartitem_p.cpp"
205 #include "moc_scatterchartitem_p.cpp"
206
206
207 QTCOMMERCIALCHART_END_NAMESPACE
207 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now