##// END OF EJS Templates
Fixed colors in spline
Marek Rosa -
r577:d1f00b1c0524
parent child
Show More
@@ -1,102 +1,114
1 1 #include "splinewidget.h"
2 2 #include "qchartview.h"
3 3 #include "qlineseries.h"
4 4 #include <QGridLayout>
5 5 #include <QPushButton>
6 6 #include "qchartaxis.h"
7 7 #include <qmath.h>
8 8
9 9 QTCOMMERCIALCHART_USE_NAMESPACE
10 10
11 11 SplineWidget::SplineWidget(QWidget *parent)
12 12 : QWidget(parent)
13 13 {
14 14 // qsrand(time(NULL));
15 15 //! [1]
16 16 //create QSplineSeries
17 series = new QSplineSeries;
17 series = new QSplineSeries(this);
18 18 //! [1]
19 19
20 20 //! [2]
21 21 // customize the series presentation settings
22 22 QPen seriesPen(Qt::blue);
23 23 seriesPen.setWidth(3);
24 series->setPen(seriesPen);
24 // series->setPen(seriesPen);
25 25 //! [2]
26 26
27 27 //! [add points to series]
28 28 //add data points to the series
29 29 series->add(QPointF(150, 100));
30 30 series->add(QPointF(200, 130));
31 31 series->add(QPointF(250, 120));
32 32 series->add(QPointF(300, 140));
33 33 series->add(QPointF(350, 160));
34 34 //! [add points to series]
35 // series->add(QPointF(400, 120));
36 // series->add(QPointF(450, 150));
37 // series->add(QPointF(500, 145));
38 // series->add(QPointF(550, 170));
35
36 QSplineSeries* series2 = new QSplineSeries;
37
38 series2->add(QPointF(400, 120));
39 series2->add(QPointF(450, 150));
40 series2->add(QPointF(500, 145));
41 series2->add(QPointF(550, 170));
42
39 43 // series->add(QPointF(600, 190));
40 44 // series->add(QPointF(650, 210));
41 45 // series->add(QPointF(700, 190));
42 46 // series->add(QPointF(750, 180));
43 47 // series->add(QPointF(800, 170));
48 QSplineSeries* series3 = new QSplineSeries;
49 series3->add(QPointF(600, 190));
50 series3->add(QPointF(650, 210));
51 series3->add(QPointF(700, 190));
52 series3->add(QPointF(750, 180));
53 series3->add(QPointF(800, 170));
44 54
45 55 //! [3]
46 56 // create chart view
47 57 QChartView* chart = new QChartView;
48 58 chart->addSeries(series);
59 chart->addSeries(series2);
60 chart->addSeries(series3);
49 61
50 62 chart->setChartTitle("Spline chart example");
51 63 chart->axisX()->setMax(1500);
52 64 chart->axisY()->setMax(500);
53 65
54 66 chart->setMinimumSize(800,600);
55 67 //! [3]
56 68
57 69 //! [4]
58 70 //add new data point button
59 71 QPushButton* addButton = new QPushButton("Add new point");
60 72 connect(addButton, SIGNAL(clicked()), this, SLOT(addNewPoint()));
61 73
62 74 // remove the last data point in the series
63 75 QPushButton* removeButton = new QPushButton("Remove point");
64 76 connect(removeButton, SIGNAL(clicked()), this, SLOT(removePoint()));
65 77 //! [4]
66 78
67 79 //! [5]
68 80 //butttons layout
69 81 QVBoxLayout* buttonsLayout = new QVBoxLayout;
70 82 buttonsLayout->addWidget(addButton);
71 83 buttonsLayout->addWidget(removeButton);
72 84 buttonsLayout->addStretch();
73 85
74 86 QGridLayout* mainLayout = new QGridLayout;
75 87 mainLayout->addWidget(chart, 1, 0);
76 88 mainLayout->addLayout(buttonsLayout, 1, 1);
77 89 setLayout(mainLayout);
78 90 //! [5]
79 91 }
80 92
81 93 //! [add point]
82 94 void SplineWidget::addNewPoint()
83 95 {
84 96 if (series->count() > 0)
85 97 series->add(QPointF(series->x(series->count() - 1) + 40 + qrand()%40, qAbs(series->y(series->count() - 1) - 50 + qrand()%100)));
86 98 else
87 99 series->add(QPointF(50, 50 + qrand()%50));
88 100 }
89 101 //! [add point]
90 102
91 103 //! [remove point]
92 104 void SplineWidget::removePoint()
93 105 {
94 106 if (series->count() > 0)
95 107 series->remove(QPointF(series->x(series->count() - 1), series->y(series->count() - 1)));
96 108 }
97 109 //! [remove point]
98 110
99 111 SplineWidget::~SplineWidget()
100 112 {
101 113
102 114 }
@@ -1,305 +1,304
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qlegend.h"
4 4 #include "qchartaxis.h"
5 5 #include <QTime>
6 6
7 7 //series
8 8 #include "qbarset.h"
9 9 #include "qbarseries.h"
10 10 #include "qstackedbarseries.h"
11 11 #include "qpercentbarseries.h"
12 12 #include "qlineseries.h"
13 13 #include "qareaseries.h"
14 14 #include "qscatterseries.h"
15 15 #include "qpieseries.h"
16 16 #include "qpieslice.h"
17 17 #include "qsplineseries.h"
18 18
19 19 //items
20 20 #include "axisitem_p.h"
21 21 #include "barpresenter_p.h"
22 22 #include "stackedbarpresenter_p.h"
23 23 #include "percentbarpresenter_p.h"
24 24 #include "linechartitem_p.h"
25 25 #include "areachartitem_p.h"
26 26 #include "scatterchartitem_p.h"
27 27 #include "piechartitem_p.h"
28 28 #include "splinechartitem_p.h"
29 29
30 30 //themes
31 31 #include "chartthemedefault_p.h"
32 32 #include "chartthemevanilla_p.h"
33 33 #include "chartthemeicy_p.h"
34 34 #include "chartthemegrayscale_p.h"
35 35 #include "chartthemescientific_p.h"
36 36
37 37
38 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 39
40 40 ChartTheme::ChartTheme(QChart::ChartTheme id)
41 41 {
42 42 m_id = id;
43 43 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
44 44 }
45 45
46 46
47 47 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
48 48 {
49 49 switch(theme) {
50 50 case QChart::ChartThemeVanilla:
51 51 return new ChartThemeVanilla();
52 52 case QChart::ChartThemeIcy:
53 53 return new ChartThemeIcy();
54 54 case QChart::ChartThemeGrayscale:
55 55 return new ChartThemeGrayscale();
56 56 case QChart::ChartThemeScientific:
57 57 return new ChartThemeScientific();
58 58 default:
59 59 return new ChartThemeDefault();
60 60 }
61 61 }
62 62
63 63 void ChartTheme::decorate(QChart* chart)
64 64 {
65 65 chart->setChartBackgroundBrush(m_backgroundGradient);
66 66 chart->setChartTitleFont(m_masterFont);
67 67 }
68 68
69 69 void ChartTheme::decorate(QLegend* legend)
70 70 {
71 71 legend->setBackgroundBrush(m_backgroundGradient);
72 72 }
73 73
74 74 void ChartTheme::decorate(QAreaSeries* series, int index)
75 75 {
76 76 QPen pen;
77 77 QBrush brush;
78 78
79 79 if (pen == series->pen()){
80 80 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
81 81 pen.setWidthF(2);
82 82 series->setPen(pen);
83 83 }
84 84
85 85 if (brush == series->brush()) {
86 86 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
87 87 series->setBrush(brush);
88 88 }
89 89 }
90 90
91 91
92 92 void ChartTheme::decorate(QLineSeries* series,int index)
93 93 {
94 94 QPen pen;
95 95 if(pen == series->pen()){
96 96 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
97 97 pen.setWidthF(2);
98 98 series->setPen(pen);
99 99 }
100 100 }
101 101
102 102 void ChartTheme::decorate(BarPresenter* item, QBarSeries* series,int index)
103 103 {
104 104 QList<QBarSet*> sets = series->barSets();
105 105 for (int i=0; i<sets.count(); i++) {
106 106 qreal pos = 0.5;
107 107 if (sets.count() > 1)
108 108 pos = (qreal) i / (qreal) (sets.count() - 1);
109 109 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
110 110 sets.at(i)->setBrush(QBrush(c));
111 111
112 112 // Pick label color as far as possible from bar color (within gradient).
113 113 // 0.3 is magic number that was picked as value that gave enough contrast with icy theme gradient :)
114 114 // TODO: better picking of label color?
115 115 if (pos < 0.3) {
116 116 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
117 117 } else {
118 118 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
119 119 }
120 120 sets.at(i)->setFloatingValuePen(QPen(c));
121 121 }
122 122 }
123 123
124 124 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarSeries* series,int index)
125 125 {
126 126 QList<QBarSet*> sets = series->barSets();
127 127 for (int i=0; i<sets.count(); i++) {
128 128 qreal pos = 0.5;
129 129 if (sets.count() > 1)
130 130 pos = (qreal) i / (qreal) (sets.count() - 1);
131 131 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
132 132 sets.at(i)->setBrush(QBrush(c));
133 133
134 134 if (pos < 0.3) {
135 135 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
136 136 } else {
137 137 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
138 138 }
139 139 sets.at(i)->setFloatingValuePen(QPen(c));
140 140 }
141 141 }
142 142
143 143 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarSeries* series,int index)
144 144 {
145 145 QList<QBarSet*> sets = series->barSets();
146 146 for (int i=0; i<sets.count(); i++) {
147 147 qreal pos = 0.5;
148 148 if (sets.count() > 1)
149 149 pos = (qreal) i / (qreal) (sets.count() - 1);
150 150 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
151 151 sets.at(i)->setBrush(QBrush(c));
152 152
153 153 if (pos < 0.3) {
154 154 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
155 155 } else {
156 156 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
157 157 }
158 158 sets.at(i)->setFloatingValuePen(QPen(c));
159 159 }
160 160 }
161 161
162 162 void ChartTheme::decorate(QScatterSeries* series, int index)
163 163 {
164 164
165 165 QPen pen;
166 166 QBrush brush;
167 167
168 168 if (pen == series->pen()) {
169 169 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
170 170 pen.setWidthF(2);
171 171 series->setPen(pen);
172 172 }
173 173
174 174 if (brush == series->brush()) {
175 175 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
176 176 series->setBrush(brush);
177 177 }
178 178 }
179 179
180 180 void ChartTheme::decorate(PieChartItem* item, QPieSeries* series, int index)
181 181 {
182 182 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
183 183 for (int i(0); i < series->slices().count(); i++) {
184 184 qreal pos = (qreal) i / (qreal) series->count();
185 185 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.1);
186 186 series->slices().at(i)->setSlicePen(penColor);
187 187 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
188 188 series->slices().at(i)->setSliceBrush(brushColor);
189 189 }
190 190 }
191 191
192 192 void ChartTheme::decorate(QSplineSeries* series, int index)
193 193 {
194 194 QPen pen;
195
196 195 if(pen == series->pen()){
197 196 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
198 197 pen.setWidthF(2);
199 198 series->setPen(pen);
200 199 }
201 200 }
202 201
203 202 void ChartTheme::decorate(QChartAxis* axis,bool axisX)
204 203 {
205 204 if (axis->isAxisVisible()) {
206 205 axis->setLabelsBrush(m_axisLabelBrush);
207 206 axis->setLabelsPen(m_axisLabelPen);
208 207 // TODO: check the axis type (x or y) should define whether to show the shades or not
209 208 if (m_backgroundShades == BackgroundShadesBoth
210 209 || (m_backgroundShades == BackgroundShadesVertical && axisX)
211 210 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX)) {
212 211 axis->setShadesPen(m_backgroundShadesPen);
213 212 axis->setShadesBrush(m_backgroundShadesBrush);
214 213 } else {
215 214 // The shades not supposed to be shown for this axis, clear possible brush and pen
216 215 axis->setShadesPen(Qt::NoPen);
217 216 axis->setShadesBrush(Qt::NoBrush);
218 217 }
219 218 axis->setAxisPen(m_axisLinePen);
220 219 axis->setGridLinePen(m_gridLinePen);
221 220 axis->setLabelsFont(m_masterFont);
222 221 }
223 222 }
224 223
225 224 void ChartTheme::generateSeriesGradients()
226 225 {
227 226 // Generate gradients in HSV color space
228 227 foreach (QColor color, m_seriesColors) {
229 228 QLinearGradient g;
230 229 qreal h = color.hsvHueF();
231 230 qreal s = color.hsvSaturationF();
232 231
233 232 // TODO: tune the algorithm to give nice results with most base colors defined in
234 233 // most themes. The rest of the gradients we can define manually in theme specific
235 234 // implementation.
236 235 QColor start = color;
237 236 start.setHsvF(h, 0.05, 0.95);
238 237 g.setColorAt(0.0, start);
239 238
240 239 g.setColorAt(0.5, color);
241 240
242 241 QColor end = color;
243 242 end.setHsvF(h, s, 0.25);
244 243 g.setColorAt(1.0, end);
245 244
246 245 m_seriesGradients << g;
247 246 }
248 247 }
249 248
250 249
251 250 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
252 251 {
253 252 Q_ASSERT(pos >=0.0 && pos <= 1.0);
254 253 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
255 254 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
256 255 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
257 256 QColor c;
258 257 c.setRgbF(r, g, b);
259 258 return c;
260 259 }
261 260
262 261 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
263 262 {
264 263 Q_ASSERT(pos >=0 && pos <= 1.0);
265 264
266 265 // another possibility:
267 266 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
268 267
269 268 QGradientStops stops = gradient.stops();
270 269 int count = stops.count();
271 270
272 271 // find previous stop relative to position
273 272 QGradientStop prev = stops.first();
274 273 for (int i=0; i<count; i++) {
275 274 QGradientStop stop = stops.at(i);
276 275 if (pos > stop.first)
277 276 prev = stop;
278 277
279 278 // given position is actually a stop position?
280 279 if (pos == stop.first) {
281 280 //qDebug() << "stop color" << pos;
282 281 return stop.second;
283 282 }
284 283 }
285 284
286 285 // find next stop relative to position
287 286 QGradientStop next = stops.last();
288 287 for (int i=count-1; i>=0; i--) {
289 288 QGradientStop stop = stops.at(i);
290 289 if (pos < stop.first)
291 290 next = stop;
292 291 }
293 292
294 293 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
295 294
296 295 qreal range = next.first - prev.first;
297 296 qreal posDelta = pos - prev.first;
298 297 qreal relativePos = posDelta / range;
299 298
300 299 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
301 300
302 301 return colorAt(prev.second, next.second, relativePos);
303 302 }
304 303
305 304 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,101 +1,101
1 1 #include "splinechartitem_p.h"
2 2 #include "chartpresenter_p.h"
3 3 #include <QPainter>
4 4
5 5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 6
7 7 SplineChartItem::SplineChartItem(QSplineSeries* series, QGraphicsItem *parent) :
8 8 XYChartItem(series, parent),
9 9 m_series(series)
10 10 {
11 11 setZValue(ChartPresenter::LineChartZValue);
12 12 QObject::connect(series,SIGNAL(updated()),this,SLOT(handleUpdated()));
13 13 handleUpdated();
14 14 }
15 15
16 16 QRectF SplineChartItem::boundingRect() const
17 17 {
18 18 return m_rect;
19 19 }
20 20
21 21 QPainterPath SplineChartItem::shape() const
22 22 {
23 23 return m_path;
24 24 }
25 25
26 26 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
27 27 {
28 28 return XYChartItem::calculateGeometryPoint(m_series->controlPoint(index));
29 29 }
30 30
31 31 void SplineChartItem::setLayout(QVector<QPointF>& points)
32 32 {
33 33
34 34 if(points.size()==0)
35 35 {
36 36 XYChartItem::setLayout(points);
37 37 return;
38 38 }
39 39
40 40 QPainterPath splinePath;
41 41 const QPointF& point = points.at(0);
42 42 splinePath.moveTo(point);
43 43
44 44 for (int i = 0; i < points.size() - 1; i++)
45 45 {
46 46 const QPointF& point = points.at(i + 1);
47 47 splinePath.cubicTo(calculateGeometryControlPoint(2 * i), calculateGeometryControlPoint(2 * i + 1), point);
48 48 }
49 49
50 50 prepareGeometryChange();
51 51 m_path = splinePath;
52 52 m_rect = splinePath.boundingRect();
53 53 XYChartItem::setLayout(points);
54 54 }
55 55
56 56 //handlers
57 57
58 58 void SplineChartItem::handleUpdated()
59 59 {
60 //m_items.setVisible(m_series->pointsVisible());
61 60 m_pen = m_series->pen();
62 61 update();
63 62 }
64 63
65 64 //painter
66 65
67 66 void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
68 67 {
69 68 Q_UNUSED(widget);
70 69 Q_UNUSED(option);
71 70 painter->save();
72 71 painter->setClipRect(clipRect());
73 painter->setPen(m_pen);
72 // painter->setPen(m_pen);
73 painter->setPen(m_series->pen());
74 74 painter->drawPath(m_path);
75 75
76 const QVector<QPointF> points = XYChartItem::points();
77
78 for (int i = 0; i < points.size() - 1; i++)
79 {
80 painter->setPen(Qt::red);
81 painter->drawEllipse(points[i], 2, 2);
82
83 painter->setPen(Qt::blue);
84 // painter->drawLine(m_series->at(i), m_series->controlPoint(2 * i));
85 // painter->drawLine(m_series->at(i + 1), m_series->controlPoint(2 * i + 1));
86 // painter->drawEllipse(calculateGeometryControlPoint(2 * i), 4, 4);
87 // painter->drawEllipse(calculateGeometryControlPoint(2 * i + 1), 4, 4);
88 }
89 if (points.count() > 0)
90 {
91 painter->setPen(Qt::red);
92 painter->drawEllipse(points[points.count() - 1], 2, 2);
93 }
76 // const QVector<QPointF> points = XYChartItem::points();
77
78 // for (int i = 0; i < points.size() - 1; i++)
79 // {
80 // painter->setPen(Qt::red);
81 // painter->drawEllipse(points[i], 2, 2);
82
83 // painter->setPen(Qt::blue);
84 // // painter->drawLine(m_series->at(i), m_series->controlPoint(2 * i));
85 // // painter->drawLine(m_series->at(i + 1), m_series->controlPoint(2 * i + 1));
86 // // painter->drawEllipse(calculateGeometryControlPoint(2 * i), 4, 4);
87 // // painter->drawEllipse(calculateGeometryControlPoint(2 * i + 1), 4, 4);
88 // }
89 // if (points.count() > 0)
90 // {
91 // painter->setPen(Qt::red);
92 // painter->drawEllipse(points[points.count() - 1], 2, 2);
93 // }
94 94 painter->restore();
95 95 }
96 96
97 97
98 98
99 99 #include "moc_splinechartitem_p.cpp"
100 100
101 101 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now