##// END OF EJS Templates
Changed BoxPlot to use domain for calculating geometry points....
Mika Salmela -
r2554:93cea193b2c2
parent child
Show More
@@ -33,9 +33,7 BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item)
33 ChartItem(series->d_func(), item),
33 ChartItem(series->d_func(), item),
34 m_series(series),
34 m_series(series),
35 m_animation(0),
35 m_animation(0),
36 m_animate(0),
36 m_animate(0)
37 m_domainMaxY(0.0),
38 m_domainMinY(0.0)
39 {
37 {
40 connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
38 connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
41 connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
39 connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
@@ -90,7 +88,7 void BoxPlotChartItem::handleDataStructureChanged()
90 }
88 }
91 updateBoxGeometry(box, s);
89 updateBoxGeometry(box, s);
92
90
93 box->updateGeometry();
91 box->updateGeometry(domain());
94
92
95 if (m_animation)
93 if (m_animation)
96 m_animation->addBox(box);
94 m_animation->addBox(box);
@@ -128,17 +126,12 void BoxPlotChartItem::handleDomainUpdated()
128 if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
126 if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
129 return;
127 return;
130
128
131 // Set my bounding rect to same as domain size
129 // Set my bounding rect to same as domain size. Add one pixel at the top (-1.0) and the bottom as 0.0 would
132 m_boundingRect.setRect(0.0, 0.0, domain()->size().width(), domain()->size().height());
130 // snip a bit off from the whisker at the grid line
131 m_boundingRect.setRect(0.0, -1.0, domain()->size().width(), domain()->size().height() + 1.0);
133
132
134 foreach (BoxWhiskers *item, m_boxTable.values()) {
133 foreach (BoxWhiskers *item, m_boxTable.values()) {
135 // Update the domain size for each BoxWhisker item
134 item->updateGeometry(domain());
136 item->setDomainSize(domain()->size());
137 if (domain()->minY() != m_domainMinY || domain()->maxY() != m_domainMaxY) {
138 item->updateGeometry();
139 m_domainMinY = domain()->minY();
140 m_domainMaxY = domain()->maxY();
141 }
142
135
143 // If the animation is set, start the animation for each BoxWhisker item
136 // If the animation is set, start the animation for each BoxWhisker item
144 if (m_animation)
137 if (m_animation)
@@ -156,7 +149,7 void BoxPlotChartItem::handleLayoutChanged()
156 if (dirty && m_animation)
149 if (dirty && m_animation)
157 presenter()->startAnimation(m_animation->boxChangeAnimation(item));
150 presenter()->startAnimation(m_animation->boxChangeAnimation(item));
158 else
151 else
159 item->updateGeometry();
152 item->updateGeometry(domain());
160 }
153 }
161 }
154 }
162
155
@@ -76,8 +76,6 protected:
76
76
77 BoxPlotAnimation *m_animation;
77 BoxPlotAnimation *m_animation;
78 bool m_animate;
78 bool m_animate;
79 qreal m_domainMaxY;
80 qreal m_domainMinY;
81
79
82 QRectF m_boundingRect;
80 QRectF m_boundingRect;
83 };
81 };
@@ -71,11 +71,10 void BoxWhiskers::setLayout(const BoxWhiskersData &data)
71 {
71 {
72 m_data = data;
72 m_data = data;
73
73
74 updateGeometry();
74 updateGeometry(m_domain);
75 update();
75 update();
76 }
76 }
77
77
78
79 QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
78 QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
80 {
79 {
81 Q_UNUSED(which)
80 Q_UNUSED(which)
@@ -89,13 +88,6 void BoxWhiskers::setGeometry(const QRectF &rect)
89 Q_UNUSED(rect)
88 Q_UNUSED(rect)
90 }
89 }
91
90
92 void BoxWhiskers::setDomainSize(const QSizeF &size)
93 {
94 m_domainSize = size;
95
96 updateBoundingRect();
97 }
98
99 QRectF BoxWhiskers::boundingRect() const
91 QRectF BoxWhiskers::boundingRect() const
100 {
92 {
101 return m_boundingRect;
93 return m_boundingRect;
@@ -109,57 +101,69 void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
109 painter->setPen(m_pen);
101 painter->setPen(m_pen);
110 painter->setBrush(m_brush);
102 painter->setBrush(m_brush);
111 painter->setClipRect(parentItem()->boundingRect());
103 painter->setClipRect(parentItem()->boundingRect());
112 painter->scale(m_domainSize.width() / m_data.m_boxItems, m_domainSize.height() / m_domain->spanY());
113 painter->drawPath(m_boxPath);
104 painter->drawPath(m_boxPath);
114 }
105 }
115
106
116 void BoxWhiskers::updateGeometry()
107 void BoxWhiskers::updateGeometry(AbstractDomain *domain)
117 {
108 {
109 m_domain = domain;
110
118 prepareGeometryChange();
111 prepareGeometryChange();
119
112
120 QPainterPath path;
113 QPainterPath path;
114 m_boxPath = path;
115 m_boundingRect = m_boxPath.boundingRect();
121
116
122 qreal columnWidth = 1.0 / m_data.m_seriesCount;
117 qreal columnWidth = 1.0 / m_data.m_seriesCount;
123 qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex;
118 qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex + m_data.m_index - 0.5;
124 qreal right = 0.75 * columnWidth + columnWidth * m_data.m_seriesIndex;
119 qreal barWidth = columnWidth / 2.0;
125 qreal middle = 0.5 * columnWidth + columnWidth * m_data.m_seriesIndex;
120
126 qreal domainMaxY = m_domain->maxY();
121 QPointF geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_upperExtreme), m_validData);
122 if (!m_validData)
123 return;
124 qreal geometryLeft = geometryPoint.x();
125 qreal geometryUpperExtreme = geometryPoint.y();
126 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left + barWidth, m_data.m_upperQuartile), m_validData);
127 if (!m_validData)
128 return;
129 qreal geometryRight = geometryPoint.x();
130 qreal geometryUpperQuartile = geometryPoint.y();
131 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerQuartile), m_validData);
132 if (!m_validData)
133 return;
134 qreal geometryLowerQuartile = geometryPoint.y();
135 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerExtreme), m_validData);
136 if (!m_validData)
137 return;
138 qreal geometryLowerExtreme = geometryPoint.y();
139 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_median), m_validData);
140 if (!m_validData)
141 return;
142 qreal geometryMedian = geometryPoint.y();
127
143
128 // Upper whisker
144 // Upper whisker
129 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
145 path.moveTo(geometryLeft, geometryUpperExtreme);
130 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
146 path.lineTo(geometryRight, geometryUpperExtreme);
131 path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
147 path.moveTo((geometryLeft + geometryRight) / 2.0, geometryUpperExtreme);
132 path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_upperQuartile);
148 path.lineTo((geometryLeft + geometryRight) / 2.0, geometryUpperQuartile);
133
149
134 // Middle Box
150 // Middle Box
135 path.addRect(left + m_data.m_index, domainMaxY - m_data.m_upperQuartile,
151 path.addRect(geometryLeft, geometryUpperQuartile, geometryRight - geometryLeft, geometryLowerQuartile - geometryUpperQuartile);
136 0.5 * columnWidth, m_data.m_upperQuartile - m_data.m_lowerQuartile);
137
152
138 // Median/mean line
153 // Median line
139 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_median);
154 path.moveTo(geometryLeft, geometryMedian);
140 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_median);
155 path.lineTo(geometryRight, geometryMedian);
141
156
142 // Lower whisker
157 // Lower whisker
143 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
158 path.moveTo(geometryLeft, geometryLowerExtreme);
144 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
159 path.lineTo(geometryRight, geometryLowerExtreme);
145 path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
160 path.moveTo((geometryLeft + geometryRight) / 2.0, geometryLowerQuartile);
146 path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerQuartile);
161 path.lineTo((geometryLeft + geometryRight) / 2.0, geometryLowerExtreme);
147
162
148 path.closeSubpath();
163 path.closeSubpath();
149
164
150 m_boxPath = path;
165 m_boxPath = path;
151
166 m_boundingRect = m_boxPath.boundingRect();
152 updateBoundingRect();
153 }
154
155 void BoxWhiskers::updateBoundingRect()
156 {
157 qreal scaleY = m_domainSize.height() / (m_domain->maxY() - m_domain->minY());
158 qreal scaleX = m_domainSize.width() / m_data.m_boxItems;
159 QRectF br = m_boxPath.boundingRect();
160
161 m_boundingRect = QRectF(br.x() * scaleX, br.y() * scaleY,
162 br.width() * scaleX, br.height() * scaleY);
163 }
167 }
164
168
165 #include "moc_boxwhiskers_p.cpp"
169 #include "moc_boxwhiskers_p.cpp"
@@ -54,7 +54,6 public:
54 void setBrush(const QBrush &brush);
54 void setBrush(const QBrush &brush);
55 void setPen(const QPen &pen);
55 void setPen(const QPen &pen);
56 void setLayout(const BoxWhiskersData &data);
56 void setLayout(const BoxWhiskersData &data);
57 void setDomainSize(const QSizeF &size);
58
57
59 void mousePressEvent(QGraphicsSceneMouseEvent *event);
58 void mousePressEvent(QGraphicsSceneMouseEvent *event);
60 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
59 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
@@ -63,14 +62,11 public:
63 QRectF boundingRect() const;
62 QRectF boundingRect() const;
64 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
63 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
65
64
66 void updateGeometry();
65 void updateGeometry(AbstractDomain *domain);
67 protected:
66 protected:
68 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
67 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
69 void setGeometry(const QRectF &rect);
68 void setGeometry(const QRectF &rect);
70
69
71 private:
72 void updateBoundingRect();
73
74 Q_SIGNALS:
70 Q_SIGNALS:
75 void clicked(QBoxSet *boxset);
71 void clicked(QBoxSet *boxset);
76 void hovered(bool status, QBoxSet *boxset);
72 void hovered(bool status, QBoxSet *boxset);
@@ -382,9 +382,9 void QBoxPlotSeriesPrivate::initializeDomain()
382 qreal maxY(domain()->maxY());
382 qreal maxY(domain()->maxY());
383
383
384 qreal x = m_boxSets.count();
384 qreal x = m_boxSets.count();
385 minX = qMin(minX, - (qreal)0.5);
385 minX = qMin(minX, qreal(-0.5));
386 minY = qMin(minY, min());
386 minY = qMin(minY, min());
387 maxX = qMax(maxX, x - (qreal)0.5);
387 maxX = qMax(maxX, x - qreal(0.5));
388 maxY = qMax(maxY, max());
388 maxY = qMax(maxY, max());
389
389
390 domain()->setRange(minX, maxX, minY, maxY);
390 domain()->setRange(minX, maxX, minY, maxY);
@@ -43,15 +43,17
43 #include <QDebug>
43 #include <QDebug>
44 #include <QStandardItemModel>
44 #include <QStandardItemModel>
45 #include <QBarCategoryAxis>
45 #include <QBarCategoryAxis>
46
46 #include <QLogValueAxis>
47
47
48 QTCOMMERCIALCHART_USE_NAMESPACE
48 QTCOMMERCIALCHART_USE_NAMESPACE
49
49
50 QString addCategories[] = {"Jul", "Aug", "Sep", "Nov", "Dec"};
50 QString addCategories[] = {"Jul", "Aug", "Sep", "Nov", "Dec"};
51 static const int maxAddCategories = 5;
51
52
52 MainWidget::MainWidget(QWidget *parent) :
53 MainWidget::MainWidget(QWidget *parent) :
53 QWidget(parent),
54 QWidget(parent),
54 m_chart(0),
55 m_chart(0),
56 m_axis(0),
55 rowPos(0),
57 rowPos(0),
56 nSeries(0),
58 nSeries(0),
57 nNewBoxes(0)
59 nNewBoxes(0)
@@ -124,7 +126,6 MainWidget::MainWidget(QWidget *parent) :
124
126
125 // Create chart view with the chart
127 // Create chart view with the chart
126 m_chartView = new QChartView(m_chart, this);
128 m_chartView = new QChartView(m_chart, this);
127 //m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
128
129
129 // Another grid layout as a main layout
130 // Another grid layout as a main layout
130 QGridLayout *mainLayout = new QGridLayout();
131 QGridLayout *mainLayout = new QGridLayout();
@@ -187,7 +188,6 void MainWidget::addSeries()
187 return;
188 return;
188
189
189 // Initial data
190 // Initial data
190 //![1]
191 QBoxSet *set0 = new QBoxSet();
191 QBoxSet *set0 = new QBoxSet();
192 QBoxSet *set1 = new QBoxSet();
192 QBoxSet *set1 = new QBoxSet();
193 QBoxSet *set2 = new QBoxSet();
193 QBoxSet *set2 = new QBoxSet();
@@ -196,7 +196,7 void MainWidget::addSeries()
196 QBoxSet *set5 = new QBoxSet();
196 QBoxSet *set5 = new QBoxSet();
197
197
198 // low bot med top upp
198 // low bot med top upp
199 *set0 << 1 << 2 << 4.4 << 13 << 15;
199 *set0 << -1 << 2 << 4 << 13 << 15;
200 *set1 << 5 << 6 << 7.5 << 8 << 12;
200 *set1 << 5 << 6 << 7.5 << 8 << 12;
201 *set2 << 3 << 5 << 5.7 << 8 << 9;
201 *set2 << 3 << 5 << 5.7 << 8 << 9;
202 *set3 << 5 << 6 << 6.8 << 7 << 8;
202 *set3 << 5 << 6 << 6.8 << 7 << 8;
@@ -219,14 +219,14 void MainWidget::addSeries()
219
219
220 m_chart->addSeries(m_series[nSeries]);
220 m_chart->addSeries(m_series[nSeries]);
221
221
222 if (nSeries == 0) {
222 if (!m_axis) {
223 QStringList categories;
223 QStringList categories;
224 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
224 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
225 m_axis = new QBarCategoryAxis();
225 m_axis = new QBarCategoryAxis();
226 m_axis->append(categories);
226 m_axis->append(categories);
227 m_chart->createDefaultAxes();
227 m_chart->createDefaultAxes();
228 m_chart->setAxisX(m_axis, m_series[nSeries]);
229 }
228 }
229 m_chart->setAxisX(m_axis, m_series[nSeries]);
230
230
231 nSeries++;
231 nSeries++;
232 }
232 }
@@ -248,7 +248,7 void MainWidget::addBox()
248 {
248 {
249 qDebug() << "BoxPlotTester::MainWidget::addBox()";
249 qDebug() << "BoxPlotTester::MainWidget::addBox()";
250
250
251 if (nSeries > 0) {
251 if (nSeries > 0 && nNewBoxes < maxAddCategories) {
252 QBoxSet *newSet = new QBoxSet();
252 QBoxSet *newSet = new QBoxSet();
253 newSet->setValue(QBoxSet::LowerExtreme, 5.0);
253 newSet->setValue(QBoxSet::LowerExtreme, 5.0);
254 newSet->setValue(QBoxSet::LowerQuartile, 6.0);
254 newSet->setValue(QBoxSet::LowerQuartile, 6.0);
@@ -256,8 +256,7 void MainWidget::addBox()
256 newSet->setValue(QBoxSet::UpperQuartile, 7.0);
256 newSet->setValue(QBoxSet::UpperQuartile, 7.0);
257 newSet->setValue(QBoxSet::UpperExtreme, 8.0);
257 newSet->setValue(QBoxSet::UpperExtreme, 8.0);
258
258
259 for (int i = 0; i < nSeries; i++)
259 m_series[0]->append(newSet);
260 m_series[i]->append(newSet);
261
260
262 m_axis->append(addCategories[nNewBoxes]);
261 m_axis->append(addCategories[nNewBoxes]);
263
262
@@ -288,11 +287,15 void MainWidget::removeBox()
288
287
289 if (nSeries > 0) {
288 if (nSeries > 0) {
290 for (int i = 0; i < nSeries; i++) {
289 for (int i = 0; i < nSeries; i++) {
291 QList<QBoxSet *> sets = m_series[i]->boxSets();
290 qDebug() << "m_series[i]->count() = " << m_series[i]->count();
292 m_series[i]->remove(sets.at(m_series[i]->count() - 3));
291 if (m_series[i]->count() > 3) {
292 QList<QBoxSet *> sets = m_series[i]->boxSets();
293 m_series[i]->remove(sets.at(m_series[i]->count() - 3));
294 }
293 }
295 }
294
296
295 m_axis->remove(m_axis->at(1));
297 if (m_axis->count() > 3)
298 m_axis->remove(m_axis->at(1));
296 } else {
299 } else {
297 qDebug() << "Create a series first";
300 qDebug() << "Create a series first";
298 }
301 }
General Comments 0
You need to be logged in to leave comments. Login now