##// END OF EJS Templates
Fixed initial bounding rect issue with bar series
Tero Ahola -
r518:1db754feb986
parent child
Show More
@@ -1,180 +1,196
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qpieseries.h>
6 6 #include <qpieslice.h>
7 #include <qbarseries.h>
8 #include <qbarset.h>
7 9 #include <QGridLayout>
8 10 #include <QFormLayout>
9 11 #include <QComboBox>
10 12 #include <QSpinBox>
11 13 #include <QCheckBox>
12 14 #include <QGroupBox>
13 15 #include <QLabel>
14 16 #include <QTime>
15 17 #include <qlineseries.h>
16 18 #include <qsplineseries.h>
17 19 #include <qscatterseries.h>
18 20 #include <qareaseries.h>
19 21
20 22 QTCOMMERCIALCHART_USE_NAMESPACE
21 23
22 24 typedef QPair<QPointF, QString> Data;
23 25 typedef QList<Data> DataList;
24 26 typedef QList<DataList> DataTable;
25 27
26 28
27 29 class MainWidget : public QWidget
28 30 {
29 31 Q_OBJECT
30 32
31 33 public:
32 34 explicit MainWidget(QWidget* parent = 0)
33 35 :QWidget(parent)
34 36 {
35 37 // set seed for random stuff
36 38 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
37 39
38 40 // generate random data
39 41 int listCount = 3;
40 42 int valueMax = 100;
41 int valueCount = 50;
43 int valueCount = 21;
42 44 for (int i(0); i < listCount; i++) {
43 45 DataList dataList;
44 46 for (int j(0); j < valueCount; j++) {
45 47 QPointF value(j + (qreal) rand() / (qreal) RAND_MAX, qrand() % valueMax);
46 48 QString label = QString::number(i) + ":" + QString::number(j);
47 49 dataList << Data(value, label);
48 50 }
49 51 m_dataTable << dataList;
50 52 }
51 53
52 54 // create layout
53 55 QGridLayout* baseLayout = new QGridLayout();
54 56
55 57 // theme combo
56 58 m_themeComboBox = new QComboBox();
57 59 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
58 60 m_themeComboBox->addItem("Vanilla", QChart::ChartThemeVanilla);
59 61 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
60 62 m_themeComboBox->addItem("Grayscale", QChart::ChartThemeGrayscale);
61 63 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
62 64 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateTheme()));
63 65 baseLayout->addWidget(new QLabel("Theme:"), 0, 0);
64 66 baseLayout->addWidget(m_themeComboBox, 0, 1);
65 67
66 68 // area chart
67 69 QChartView *chart = new QChartView();
68 70 chart->setChartTitle("Area chart");
69 71 chart->setRenderHint(QPainter::Antialiasing);
70 72 baseLayout->addWidget(chart, 1, 0);
71 73 {
72 74 QLineSeries *series1 = new QLineSeries(chart);
73 75 foreach (Data data, m_dataTable.first())
74 76 series1->add(data.first);
75 77 QLineSeries *series2 = new QLineSeries(chart);
76 78 foreach (Data data, m_dataTable.last())
77 79 series2->add(data.first);
78 80 QAreaSeries *series = new QAreaSeries(series1, series2);
79 81 chart->addSeries(series);
80 82 }
81 83 m_charts << chart;
82 84
83 85 // bar chart
84 86 chart = new QChartView();
85 87 chart->setChartTitle("bar chart");
86 88 chart->setRenderHint(QPainter::Antialiasing);
87 89 baseLayout->addWidget(chart, 1, 1);
90 {
91 QStringList categories;
92 // TODO: categories
93 for (int i(0); i < valueCount; i++)
94 categories << QString::number(i);
95 QBarSeries* series = new QBarSeries(categories, chart);
96 for (int i(0); i < m_dataTable.count(); i++) {
97 QBarSet *set = new QBarSet("Set" + QString::number(i));
98 foreach (Data data, m_dataTable[i])
99 *set << data.first.y();
100 series->addBarSet(set);
101 }
102 chart->addSeries(series);
103 }
88 104 m_charts << chart;
89 105
90 106 // line chart
91 107 chart = new QChartView();
92 108 chart->setChartTitle("line chart");
93 109 chart->setRenderHint(QPainter::Antialiasing);
94 110 baseLayout->addWidget(chart, 1, 2);
95 111 foreach (DataList list, m_dataTable) {
96 112 QLineSeries *series = new QLineSeries(chart);
97 113 foreach (Data data, list)
98 114 series->add(data.first);
99 115 chart->addSeries(series);
100 116 }
101 117 m_charts << chart;
102 118
103 119 // pie chart
104 120 chart = new QChartView();
105 121 chart->setChartTitle("pie chart");
106 122 chart->setRenderHint(QPainter::Antialiasing);
107 123 baseLayout->addWidget(chart, 2, 0);
108 124
109 125 qreal pieSize = 1.0 / m_dataTable.count();
110 126 for (int i=0; i<m_dataTable.count(); i++) {
111 127 QPieSeries *series = new QPieSeries(chart);
112 128 foreach (Data data, m_dataTable[i])
113 129 series->add(data.first.y(), data.second);
114 130 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
115 131 series->setPieSize(pieSize);
116 132 series->setPiePosition(hPos, 0.5);
117 133 chart->addSeries(series);
118 134 }
119 135 m_charts << chart;
120 136
121 137 // spine chart
122 138 chart = new QChartView();
123 139 chart->setChartTitle("spline chart");
124 140 chart->setRenderHint(QPainter::Antialiasing);
125 141 baseLayout->addWidget(chart, 2, 1);
126 142 foreach (DataList list, m_dataTable) {
127 143 QSplineSeries *series = new QSplineSeries(chart);
128 144 foreach (Data data, list)
129 145 series->add(data.first);
130 146 chart->addSeries(series);
131 147 }
132 148 m_charts << chart;
133 149
134 150 // scatter chart
135 151 chart = new QChartView();
136 152 chart->setChartTitle("scatter chart");
137 153 chart->setRenderHint(QPainter::Antialiasing);
138 154 baseLayout->addWidget(chart, 2, 2);
139 155 foreach (DataList list, m_dataTable) {
140 156 QScatterSeries *series = new QScatterSeries(chart);
141 157 foreach (Data data, list)
142 158 series->add(data.first);
143 159 chart->addSeries(series);
144 160 }
145 161 m_charts << chart;
146 162
147 163 setLayout(baseLayout);
148 164 }
149 165
150 166 public Q_SLOTS:
151 167
152 168 void updateTheme()
153 169 {
154 170 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
155 171 foreach (QChartView *chart, m_charts)
156 172 chart->setChartTheme(theme);
157 173 }
158 174
159 175 private:
160 176 QList<QChartView*> m_charts;
161 177 QComboBox *m_themeComboBox;
162 178 DataTable m_dataTable;
163 179 };
164 180
165 181 int main(int argc, char *argv[])
166 182 {
167 183 QApplication a(argc, argv);
168 184
169 185 QMainWindow window;
170 186
171 187 MainWidget* widget = new MainWidget();
172 188
173 189 window.setCentralWidget(widget);
174 190 window.resize(900, 600);
175 191 window.show();
176 192
177 193 return a.exec();
178 194 }
179 195
180 196 #include "main.moc"
@@ -1,89 +1,93
1 1 #include "bar_p.h"
2 2 #include <QDebug>
3 3 #include <QPainter>
4 4 #include <QGraphicsSceneEvent>
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 Bar::Bar(QString category, QGraphicsItem *parent)
9 : QGraphicsObject(parent)
10 ,mCategory(category)
9 : QGraphicsObject(parent),
10 mCategory(category),
11 mXpos(0),
12 mYpos(0),
13 mWidth(0),
14 mHeight(0)
11 15 {
12 16 setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
13 17 setAcceptHoverEvents(true);
14 18 }
15 19
16 20 void Bar::setSize(const QSizeF& size)
17 21 {
18 22 mWidth = size.width();
19 23 mHeight = size.height();
20 24 }
21 25
22 26
23 27 void Bar::resize( qreal w, qreal h )
24 28 {
25 29 mWidth = w;
26 30 mHeight = h;
27 31 }
28 32
29 33 void Bar::setPos(qreal x, qreal y)
30 34 {
31 35 mXpos = x;
32 36 mYpos = y;
33 37 }
34 38
35 39 void Bar::setPen(QPen pen)
36 40 {
37 41 mPen = pen;
38 42 }
39 43
40 44 void Bar::setBrush(QBrush brush)
41 45 {
42 46 mBrush = brush;
43 47 }
44 48
45 49 void Bar::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
46 50 {
47 51 if (0 == mHeight) {
48 52 return;
49 53 }
50 54 painter->setBrush(mBrush);
51 55
52 56 // This compensates for rounding errors. drawRect takes ints and cumulative error of pos + size may be over 1.
53 57 int x0 = mXpos;
54 58 int x1 = (mXpos + mWidth);
55 59 int w = x1-x0;
56 60 int y0 = mYpos;
57 61 int y1 = (mYpos + mHeight);
58 62 int h = y1-y0;
59 63 painter->drawRect(x0, y0 ,w ,h);
60 64 }
61 65
62 66 QRectF Bar::boundingRect() const
63 67 {
64 68 QRectF r(mXpos, mYpos, mWidth, mHeight);
65 69 return r;
66 70 }
67 71
68 72 void Bar::mousePressEvent(QGraphicsSceneMouseEvent* event)
69 73 {
70 74 if (event->button() == Qt::LeftButton) {
71 75 emit clicked(mCategory);
72 76 } else if (event->button() == Qt::RightButton) {
73 77 emit rightClicked(mCategory);
74 78 }
75 79 }
76 80
77 81 void Bar::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
78 82 {
79 83 emit hoverEntered(event->lastScreenPos());
80 84 }
81 85
82 86 void Bar::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
83 87 {
84 88 emit hoverLeaved();
85 89 }
86 90
87 91 #include "moc_bar_p.cpp"
88 92
89 93 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,178 +1,180
1 1 #include "barpresenterbase_p.h"
2 2 #include "bar_p.h"
3 3 #include "barvalue_p.h"
4 4 #include "separator_p.h"
5 5 #include "qbarset.h"
6 6 #include "qbarseries.h"
7 7 #include "qchart.h"
8 8 #include "qchartaxis.h"
9 9 #include "qchartaxiscategories.h"
10 10 #include <QDebug>
11 11 #include <QToolTip>
12 12
13 13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 14
15 BarPresenterBase::BarPresenterBase(QBarSeries *series, QChart *parent)
16 : ChartItem(parent)
17 ,mLayoutSet(false)
18 ,mSeries(series)
19 ,mChart(parent)
15 BarPresenterBase::BarPresenterBase(QBarSeries *series, QChart *parent) :
16 ChartItem(parent),
17 mLayoutSet(false),
18 mSeries(series),
19 mChart(parent),
20 mWidth(0),
21 mHeight(0)
20 22 {
21 23 connect(series,SIGNAL(showToolTip(QPoint,QString)),this,SLOT(showToolTip(QPoint,QString)));
22 24 connect(series,SIGNAL(enableSeparators(bool)),this,SLOT(enableSeparators(bool)));
23 25 enableSeparators(series->separatorsVisible());
24 26 initAxisLabels();
25 27 dataChanged();
26 28 }
27 29
28 30 BarPresenterBase::~BarPresenterBase()
29 31 {
30 32 disconnect(this,SLOT(showToolTip(QPoint,QString)));
31 33 disconnect(this,SLOT(enableSeparators(bool)));
32 34 }
33 35
34 36 void BarPresenterBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
35 37 {
36 38 if (!mLayoutSet) {
37 39 qDebug() << "BarPresenterBase::paint called without layout set. Aborting.";
38 40 return;
39 41 }
40 42 foreach(QGraphicsItem* i, childItems()) {
41 43 i->paint(painter,option,widget);
42 44 }
43 45 }
44 46
45 47 QRectF BarPresenterBase::boundingRect() const
46 48 {
47 return QRectF(0,0,mWidth,mHeight);
49 return QRectF(0, 0, mWidth, mHeight);
48 50 }
49 51
50 52 void BarPresenterBase::dataChanged()
51 53 {
52 54 // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them?
53 55 // Delete old bars
54 56 foreach (QGraphicsItem* item, childItems()) {
55 57 delete item;
56 58 }
57 59
58 60 mBars.clear();
59 61 mSeparators.clear();
60 62 mFloatingValues.clear();
61 63
62 64 // Create new graphic items for bars
63 65 for (int c=0; c<mSeries->categoryCount(); c++) {
64 66 QString category = mSeries->categoryName(c);
65 67 for (int s=0; s<mSeries->barsetCount(); s++) {
66 68 QBarSet *set = mSeries->barsetAt(s);
67 69 Bar *bar = new Bar(category,this);
68 70 childItems().append(bar);
69 71 mBars.append(bar);
70 72 connect(bar,SIGNAL(clicked(QString)),set,SIGNAL(clicked(QString)));
71 73 connect(bar,SIGNAL(rightClicked(QString)),set,SIGNAL(rightClicked(QString)));
72 74 connect(bar,SIGNAL(hoverEntered(QPoint)),set,SLOT(barHoverEnterEvent(QPoint)));
73 75 connect(bar,SIGNAL(hoverLeaved()),set,SLOT(barHoverLeaveEvent()));
74 76 }
75 77 }
76 78
77 79 // Create separators
78 80 int count = mSeries->categoryCount() - 1; // There is one less separator than columns
79 81 for (int i=0; i<count; i++) {
80 82 Separator* sep = new Separator(this);
81 83 sep->setVisible(mSeries->separatorsVisible());
82 84 childItems().append(sep);
83 85 mSeparators.append(sep);
84 86 }
85 87
86 88 // Create floating values
87 89 for (int category=0; category<mSeries->categoryCount(); category++) {
88 90 for (int s=0; s<mSeries->barsetCount(); s++) {
89 91 QBarSet *set = mSeries->barsetAt(s);
90 92 BarValue *value = new BarValue(*set, this);
91 93 childItems().append(value);
92 94 mFloatingValues.append(value);
93 95 connect(set,SIGNAL(toggleFloatingValues()),value,SLOT(toggleVisible()));
94 96 }
95 97 }
96 98 }
97 99
98 100 void BarPresenterBase::initAxisLabels()
99 101 {
100 102 int count = mSeries->categoryCount();
101 103 if (0 == count) {
102 104 return;
103 105 }
104 106
105 107 mChart->axisX()->setTicksCount(count+2);
106 108
107 109 qreal min = 0;
108 110 qreal max = count+1;
109 111
110 112 mChart->axisX()->setMin(min);
111 113 mChart->axisX()->setMax(max);
112 114
113 115 QChartAxisCategories* categories = mChart->axisX()->categories();
114 116 categories->clear();
115 117 for (int i=0; i<count; i++) {
116 118 categories->insert(i+1,mSeries->categoryName(i));
117 119 }
118 120
119 121
120 122
121 123 mChart->axisX()->setLabelsVisible(true);
122 124 }
123 125
124 126 //handlers
125 127
126 128 void BarPresenterBase::handleModelChanged(int index)
127 129 {
128 130 // qDebug() << "BarPresenterBase::handleModelChanged" << index;
129 131 dataChanged();
130 132 }
131 133
132 134 void BarPresenterBase::handleDomainChanged(const Domain& domain)
133 135 {
134 136 qDebug() << "BarPresenterBase::handleDomainChanged";
135 137 /*
136 138 int count = mSeries->categoryCount();
137 139 if (0 == count) {
138 140 return;
139 141 }
140 142
141 143 // Position labels to domain
142 144 qreal min = domain.minX();
143 145 qreal max = domain.maxX();
144 146 qreal step = (max-min)/count;
145 147 QChartAxisCategories& categories = mChart->axisX()->categories();
146 148 categories.clear();
147 149 for (int i=0; i<count; i++) {
148 150 categories.insert(min,mSeries->categoryName(i));
149 151 min += step;
150 152 }
151 153 */
152 154 }
153 155
154 156 void BarPresenterBase::handleGeometryChanged(const QRectF& rect)
155 157 {
156 158 mWidth = rect.width();
157 159 mHeight = rect.height();
158 160 layoutChanged();
159 161 mLayoutSet = true;
160 162 setPos(rect.topLeft());
161 163 }
162 164
163 165 void BarPresenterBase::showToolTip(QPoint pos, QString tip)
164 166 {
165 167 // TODO: cool tooltip instead of default
166 168 QToolTip::showText(pos,tip);
167 169 }
168 170
169 171 void BarPresenterBase::enableSeparators(bool enabled)
170 172 {
171 173 for (int i=0; i<mSeparators.count(); i++) {
172 174 mSeparators.at(i)->setVisible(enabled);
173 175 }
174 176 }
175 177
176 178 #include "moc_barpresenterbase_p.cpp"
177 179
178 180 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,66 +1,70
1 1 #include "barvalue_p.h"
2 2 #include <QPainter>
3 3 #include <QPen>
4 4
5 5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 6
7 7 BarValue::BarValue(QBarSet &set, QGraphicsItem *parent)
8 : QGraphicsObject(parent)
9 ,mBarSet(set)
8 : QGraphicsObject(parent),
9 mBarSet(set),
10 mXpos(0),
11 mYpos(0),
12 mWidth(0),
13 mHeight(0)
10 14 {
11 15 setVisible(false);
12 16 }
13 17
14 18 void BarValue::setValueString(QString str)
15 19 {
16 20 mValueString = str;
17 21 }
18 22
19 23 QString BarValue::valueString()
20 24 {
21 25 return mValueString;
22 26 }
23 27
24 28 void BarValue::setPen(const QPen pen)
25 29 {
26 30 mPen = pen;
27 31 }
28 32
29 33 QPen BarValue::pen() const
30 34 {
31 35 return mPen;
32 36 }
33 37
34 38 void BarValue::resize(qreal w, qreal h)
35 39 {
36 40 mWidth = w;
37 41 mHeight = h;
38 42 }
39 43
40 44 void BarValue::setPos(qreal x, qreal y)
41 45 {
42 46 mXpos = x;
43 47 mYpos = y;
44 48 }
45 49
46 50 void BarValue::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
47 51 {
48 52 if (isVisible()) {
49 53 painter->setPen(mPen);
50 54 painter->drawText(boundingRect(),mValueString);
51 55 }
52 56 }
53 57
54 58 QRectF BarValue::boundingRect() const
55 59 {
56 60 QRectF r(mXpos, mYpos, mWidth, mHeight);
57 61 return r;
58 62 }
59 63
60 64 void BarValue::toggleVisible()
61 65 {
62 66 setVisible(!isVisible());
63 67 }
64 68
65 69 #include "moc_barvalue_p.cpp"
66 70 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now