##// END OF EJS Templates
better legend detach layout. updated legend example
sauimone -
r1444:0ed586503264
parent child
Show More
@@ -27,6 +27,7
27 #include <QBarSet>
27 #include <QBarSet>
28 #include <QBarSeries>
28 #include <QBarSeries>
29 #include <QLegend>
29 #include <QLegend>
30 #include <QFormLayout>
30
31
31 QTCOMMERCIALCHART_USE_NAMESPACE
32 QTCOMMERCIALCHART_USE_NAMESPACE
32
33
@@ -49,25 +50,52 MainWidget::MainWidget(QWidget *parent) :
49 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
50 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
50 m_buttonLayout->addWidget(removeBarsetButton, 3, 0);
51 m_buttonLayout->addWidget(removeBarsetButton, 3, 0);
51
52
53 QPushButton *leftButton = new QPushButton("Align legend left");
54 connect(leftButton, SIGNAL(clicked()), this, SLOT(setLegendLeft()));
55 m_buttonLayout->addWidget(leftButton, 4, 0);
56
57 QPushButton *rightButton = new QPushButton("Align legend right");
58 connect(rightButton, SIGNAL(clicked()), this, SLOT(setLegendRight()));
59 m_buttonLayout->addWidget(rightButton, 5, 0);
60
61 QPushButton *topButton = new QPushButton("Align legend top");
62 connect(topButton, SIGNAL(clicked()), this, SLOT(setLegendTop()));
63 m_buttonLayout->addWidget(topButton, 6, 0);
64
65 QPushButton *bottomButton = new QPushButton("Align legend bottom");
66 connect(bottomButton, SIGNAL(clicked()), this, SLOT(setLegendBottom()));
67 m_buttonLayout->addWidget(bottomButton, 7, 0);
68
69 m_legendPosX = new QDoubleSpinBox();
70 m_legendPosY = new QDoubleSpinBox();
71 m_legendWidth = new QDoubleSpinBox();
72 m_legendHeight = new QDoubleSpinBox();
73
74 connect(m_legendPosX, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
75 connect(m_legendPosY, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
76 connect(m_legendWidth, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
77 connect(m_legendHeight, SIGNAL(valueChanged(double)), this, SLOT(updateLegendLayout()));
78
79 QFormLayout* legendLayout = new QFormLayout();
80 legendLayout->addRow("Horizontal position", m_legendPosX);
81 legendLayout->addRow("Vertical position", m_legendPosY);
82 legendLayout->addRow("Width", m_legendWidth);
83 legendLayout->addRow("Height", m_legendHeight);
84 m_legendSettings = new QGroupBox("Detached legend");
85 m_legendSettings->setLayout(legendLayout);
86 m_buttonLayout->addWidget(m_legendSettings);
87 m_legendSettings->setVisible(false);
88
52 // Create chart view with the chart
89 // Create chart view with the chart
53 //![1]
90 //![1]
54 m_chart = new QChart();
91 m_chart = new QChart();
55 m_chartView = new QChartView(m_chart, this);
92 m_chartView = new QChartView(m_chart, this);
56 m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
57 //![1]
93 //![1]
58
94
59 // Create custom scene and view, where detached legend will be drawn
60 //![2]
61 m_customView = new QGraphicsView(this);
62 m_customScene = new QGraphicsScene(this);
63 m_customView->setScene(m_customScene);
64 //![2]
65
66 // Create layout for grid and detached legend
95 // Create layout for grid and detached legend
67 m_mainLayout = new QGridLayout();
96 m_mainLayout = new QGridLayout();
68 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
97 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
69 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
98 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
70 m_mainLayout->addWidget(m_customView, 0, 2, 3, 1);
71 setLayout(m_mainLayout);
99 setLayout(m_mainLayout);
72
100
73 createSeries();
101 createSeries();
@@ -93,43 +121,61 void MainWidget::createSeries()
93 //![3]
121 //![3]
94 }
122 }
95
123
124 void MainWidget::showLegendSpinbox()
125 {
126 m_legendSettings->setVisible(true);
127 QRectF chartViewRect = m_chartView->rect();
128 QRectF legendRect = m_chart->legend()->boundingRect();
129
130 m_legendPosX->setMinimum(0);
131 m_legendPosX->setMaximum(chartViewRect.width());
132 m_legendPosX->setValue(150);
133
134 m_legendPosY->setMinimum(0);
135 m_legendPosY->setMaximum(chartViewRect.height());
136 m_legendPosY->setValue(150);
137
138 m_legendWidth->setMinimum(0);
139 m_legendWidth->setMaximum(chartViewRect.width());
140 m_legendWidth->setValue(150);
141
142 m_legendHeight->setMinimum(0);
143 m_legendHeight->setMaximum(chartViewRect.height());
144 m_legendHeight->setValue(64);
145 }
146
147 void MainWidget::hideLegendSpinbox()
148 {
149 m_legendSettings->setVisible(false);
150 }
151
152
96 void MainWidget::detachLegend()
153 void MainWidget::detachLegend()
97 {
154 {
98 // Detach legend from chart and
99 // put legend to our custom scene
100 //![4]
155 //![4]
101 QLegend *legend = m_chart->legend();
156 QLegend *legend = m_chart->legend();
102 legend->detachFromChart();
157 legend->detachFromChart();
103 legend->setGeometry(m_customView->rect());
158
104 m_customScene->addItem(legend);
159 m_chart->legend()->setBackgroundVisible(true);
160 m_chart->legend()->setBrush(QBrush(QColor(128,128,128,128)));
105 //![4]
161 //![4]
106
162
107 // This forces redraw
163 showLegendSpinbox();
108 QSize delta(1,1);
164 updateLegendLayout();
109 resize(size() + delta);
165 update();
110 resize(size() - delta);
111 }
166 }
112
167
113
168
114 void MainWidget::attachLegend()
169 void MainWidget::attachLegend()
115 {
170 {
116 // Remove legend from custom scene and put it back to chartview scene.
117 // Attach legend back to chart, so that layout works.
118
119 //![5]
171 //![5]
120 QLegend *legend = m_chart->legend();
172 QLegend *legend = m_chart->legend();
121
173 legend->attachToChart();
122 if (m_customScene->items().contains(legend)) {
174 m_chart->legend()->setBackgroundVisible(false);
123 m_customScene->removeItem(legend);
124 m_chartView->scene()->addItem(legend);
125 legend->attachToChart();
126 }
127 //![5]
175 //![5]
128
176
129 // This forces redraw
177 hideLegendSpinbox();
130 QSize delta(1,1);
178 update();
131 resize(size() + delta);
132 resize(size() - delta);
133 }
179 }
134
180
135 void MainWidget::addBarset()
181 void MainWidget::addBarset()
@@ -147,3 +193,32 void MainWidget::removeBarset()
147 m_series->remove(sets.at(sets.count()-1));
193 m_series->remove(sets.at(sets.count()-1));
148 }
194 }
149 }
195 }
196
197 void MainWidget::setLegendLeft()
198 {
199 m_chart->legend()->setAlignment(Qt::AlignLeft);
200 }
201
202 void MainWidget::setLegendRight()
203 {
204 m_chart->legend()->setAlignment(Qt::AlignRight);
205 }
206
207 void MainWidget::setLegendTop()
208 {
209 m_chart->legend()->setAlignment(Qt::AlignTop);
210 }
211
212 void MainWidget::setLegendBottom()
213 {
214 m_chart->legend()->setAlignment(Qt::AlignBottom);
215 }
216
217 void MainWidget::updateLegendLayout()
218 {
219 m_chart->legend()->setGeometry(m_legendPosX->value()
220 ,m_legendPosY->value()
221 ,m_legendWidth->value()
222 ,m_legendHeight->value());
223 m_chart->legend()->update();
224 }
@@ -28,6 +28,8
28 #include <QGraphicsWidget>
28 #include <QGraphicsWidget>
29 #include <QGridLayout>
29 #include <QGridLayout>
30 #include <QGraphicsGridLayout>
30 #include <QGraphicsGridLayout>
31 #include <QDoubleSpinBox>
32 #include <QGroupBox>
31
33
32 QTCOMMERCIALCHART_USE_NAMESPACE
34 QTCOMMERCIALCHART_USE_NAMESPACE
33
35
@@ -36,9 +38,10 class MainWidget : public QWidget
36 Q_OBJECT
38 Q_OBJECT
37 public:
39 public:
38 explicit MainWidget(QWidget *parent = 0);
40 explicit MainWidget(QWidget *parent = 0);
39
40 void createSeries();
41 void createSeries();
41
42 void showLegendSpinbox();
43 void hideLegendSpinbox();
44
42 signals:
45 signals:
43
46
44 public slots:
47 public slots:
@@ -47,6 +50,13 public slots:
47 void addBarset();
50 void addBarset();
48 void removeBarset();
51 void removeBarset();
49
52
53 void setLegendLeft();
54 void setLegendRight();
55 void setLegendTop();
56 void setLegendBottom();
57
58 void updateLegendLayout();
59
50 private:
60 private:
51
61
52 QChart *m_chart;
62 QChart *m_chart;
@@ -56,8 +66,12 private:
56 QGridLayout *m_mainLayout;
66 QGridLayout *m_mainLayout;
57 QGridLayout *m_buttonLayout;
67 QGridLayout *m_buttonLayout;
58
68
59 QGraphicsView *m_customView;
69 // For detached layout
60 QGraphicsScene *m_customScene;
70 QGroupBox* m_legendSettings;
71 QDoubleSpinBox *m_legendPosX;
72 QDoubleSpinBox *m_legendPosY;
73 QDoubleSpinBox *m_legendWidth;
74 QDoubleSpinBox *m_legendHeight;
61 };
75 };
62
76
63 #endif // MAINWIDGET_H
77 #endif // MAINWIDGET_H
@@ -318,8 +318,6 void ChartPresenter::updateLayout()
318 // recalculate legend position
318 // recalculate legend position
319 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
319 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
320
320
321 QRect legendRect;
322
323 // Reserve some space for legend
321 // Reserve some space for legend
324 switch (legend->alignment()) {
322 switch (legend->alignment()) {
325
323
@@ -382,7 +380,9 void ChartPresenter::updateLayout()
382
380
383 QRectF chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
381 QRectF chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
384
382
385 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
383 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
384 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
385 }
386
386
387 if(m_chartRect!=chartRect && chartRect.isValid()){
387 if(m_chartRect!=chartRect && chartRect.isValid()){
388 m_chartRect=chartRect;
388 m_chartRect=chartRect;
@@ -320,29 +320,38 QLegendPrivate::~QLegendPrivate()
320
320
321 void QLegendPrivate::setOffset(qreal x, qreal y)
321 void QLegendPrivate::setOffset(qreal x, qreal y)
322 {
322 {
323
323 bool scrollHorizontal = true;
324 switch(m_alignment) {
324 switch(m_alignment) {
325
326 case Qt::AlignTop:
325 case Qt::AlignTop:
327 case Qt::AlignBottom: {
326 case Qt::AlignBottom: {
328 if(m_width<=m_rect.width()) return;
327 scrollHorizontal = true;
329
330 if (x != m_offsetX) {
331 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
332 m_markers->setPos(-m_offsetX,m_rect.top());
333 }
334 break;
328 break;
335 }
329 }
336 case Qt::AlignLeft:
330 case Qt::AlignLeft:
337 case Qt::AlignRight: {
331 case Qt::AlignRight: {
332 scrollHorizontal = false;
333 break;
334 }
335 }
338
336
339 if(m_height<=m_rect.height()) return;
337 // If detached, the scrolling and layout logic is inverted.
338 if (!m_attachedToChart) {
339 scrollHorizontal = !scrollHorizontal;
340 }
340
341
341 if (y != m_offsetY) {
342 if (scrollHorizontal) {
342 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
343 if(m_width<=m_rect.width()) return;
343 m_markers->setPos(m_rect.left(),-m_offsetY);
344
344 }
345 if (x != m_offsetX) {
345 break;
346 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
347 m_markers->setPos(-m_offsetX,m_rect.top());
348 }
349 } else {
350 if(m_height<=m_rect.height()) return;
351
352 if (y != m_offsetY) {
353 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
354 m_markers->setPos(m_rect.left(),-m_offsetY);
346 }
355 }
347 }
356 }
348 }
357 }
@@ -350,6 +359,11 void QLegendPrivate::setOffset(qreal x, qreal y)
350
359
351 void QLegendPrivate::updateLayout()
360 void QLegendPrivate::updateLayout()
352 {
361 {
362 if (!m_attachedToChart) {
363 updateDetachedLayout();
364 return;
365 }
366
353 m_offsetX=0;
367 m_offsetX=0;
354 QList<QGraphicsItem *> items = m_markers->childItems();
368 QList<QGraphicsItem *> items = m_markers->childItems();
355
369
@@ -406,8 +420,136 void QLegendPrivate::updateLayout()
406 break;
420 break;
407 }
421 }
408
422
409 if (m_attachedToChart) {
423 m_presenter->updateLayout();
410 m_presenter->updateLayout();
424 }
425
426 void QLegendPrivate::updateDetachedLayout()
427 {
428 m_offsetX=0;
429 QList<QGraphicsItem *> items = m_markers->childItems();
430
431 if(items.isEmpty()) return;
432
433 m_minWidth = 0;
434 m_minHeight = 0;
435
436 switch (m_alignment) {
437 case Qt::AlignTop: {
438 QPointF point = m_rect.topLeft();
439 m_width = 0;
440 m_height = 0;
441 for (int i=0; i<items.count(); i++) {
442 QGraphicsItem *item = items.at(i);
443 const QRectF& rect = item->boundingRect();
444 qreal w = rect.width();
445 qreal h = rect.height();
446 m_minWidth = qMax(m_minWidth,w);
447 m_minHeight = qMax(m_minHeight,rect.height());
448 m_height = qMax(m_height,h);
449 item->setPos(point.x(),point.y());
450 point.setX(point.x() + w);
451 if (point.x() + w > m_rect.topLeft().x() + m_rect.width()) {
452 // Next item would go off rect.
453 point.setX(m_rect.topLeft().x());
454 point.setY(point.y() + h);
455 if (i+1 < items.count()) {
456 m_height += h;
457 }
458 }
459 }
460 m_markers->setPos(m_rect.topLeft());
461 m_width = m_minWidth;
462 }
463 break;
464 case Qt::AlignBottom: {
465 QPointF point = m_rect.bottomLeft();
466 m_width = 0;
467 m_height = 0;
468 for (int i=0; i<items.count(); i++) {
469 QGraphicsItem *item = items.at(i);
470 const QRectF& rect = item->boundingRect();
471 qreal w = rect.width();
472 qreal h = rect.height();
473 m_minWidth = qMax(m_minWidth,w);
474 m_minHeight = qMax(m_minHeight,rect.height());
475 m_height = qMax(m_height,h);
476 item->setPos(point.x(),point.y() - h);
477 point.setX(point.x() + w);
478 if (point.x() + w > m_rect.bottomLeft().x() + m_rect.width()) {
479 // Next item would go off rect.
480 point.setX(m_rect.bottomLeft().x());
481 point.setY(point.y() - h);
482 if (i+1 < items.count()) {
483 m_height += h;
484 }
485 }
486 }
487 m_markers->setPos(m_rect.topLeft());
488 m_width = m_minWidth;
489 }
490 break;
491 case Qt::AlignLeft: {
492 QPointF point = m_rect.topLeft();
493 m_width = 0;
494 m_height = 0;
495 qreal maxWidth = 0;
496 for (int i=0; i<items.count(); i++) {
497 QGraphicsItem *item = items.at(i);
498 const QRectF& rect = item->boundingRect();
499 qreal w = rect.width();
500 qreal h = rect.height();
501 m_minWidth = qMax(m_minWidth,rect.width());
502 m_minHeight = qMax(m_minHeight,h);
503 maxWidth = qMax(maxWidth,w);
504 m_width = qMax(m_width, maxWidth);
505 item->setPos(point.x(),point.y());
506 point.setY(point.y() + h);
507 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
508 // Next item would go off rect.
509 point.setX(point.x() + maxWidth);
510 point.setY(m_rect.topLeft().y());
511 if (i+1 < items.count()) {
512 m_width += maxWidth;
513 maxWidth = 0;
514 }
515 }
516 }
517 m_markers->setPos(m_rect.topLeft());
518 m_height = m_minHeight;
519 }
520 break;
521 case Qt::AlignRight: {
522 QPointF point = m_rect.topRight();
523 m_width = 0;
524 m_height = 0;
525 qreal maxWidth = 0;
526 for (int i=0; i<items.count(); i++) {
527 QGraphicsItem *item = items.at(i);
528 const QRectF& rect = item->boundingRect();
529 qreal w = rect.width();
530 qreal h = rect.height();
531 m_minWidth = qMax(m_minWidth,rect.width());
532 m_minHeight = qMax(m_minHeight,h);
533 maxWidth = qMax(maxWidth,w);
534 m_width = qMax(m_width, maxWidth);
535 item->setPos(point.x() - w,point.y());
536 point.setY(point.y() + h);
537 if (point.y() + h > m_rect.topLeft().y() + m_rect.height()) {
538 // Next item would go off rect.
539 point.setX(point.x() - maxWidth);
540 point.setY(m_rect.topLeft().y());
541 if (i+1 < items.count()) {
542 m_width += maxWidth;
543 maxWidth = 0;
544 }
545 }
546 }
547 m_markers->setPos(m_rect.topLeft());
548 m_height = m_minHeight;
549 }
550 break;
551 default:
552 break;
411 }
553 }
412 }
554 }
413
555
@@ -47,6 +47,7 public:
47
47
48 void setOffset(qreal x, qreal y);
48 void setOffset(qreal x, qreal y);
49 void updateLayout();
49 void updateLayout();
50 void updateDetachedLayout();
50 void attachToChart();
51 void attachToChart();
51
52
52 public Q_SLOTS:
53 public Q_SLOTS:
General Comments 0
You need to be logged in to leave comments. Login now