##// END OF EJS Templates
better legend detach layout. updated legend example
sauimone -
r1444:0ed586503264
parent child
Show More
@@ -27,6 +27,7
27 27 #include <QBarSet>
28 28 #include <QBarSeries>
29 29 #include <QLegend>
30 #include <QFormLayout>
30 31
31 32 QTCOMMERCIALCHART_USE_NAMESPACE
32 33
@@ -49,25 +50,52 MainWidget::MainWidget(QWidget *parent) :
49 50 connect(removeBarsetButton, SIGNAL(clicked()), this, SLOT(removeBarset()));
50 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 89 // Create chart view with the chart
53 90 //![1]
54 91 m_chart = new QChart();
55 92 m_chartView = new QChartView(m_chart, this);
56 m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
57 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 95 // Create layout for grid and detached legend
67 96 m_mainLayout = new QGridLayout();
68 97 m_mainLayout->addLayout(m_buttonLayout, 0, 0);
69 98 m_mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
70 m_mainLayout->addWidget(m_customView, 0, 2, 3, 1);
71 99 setLayout(m_mainLayout);
72 100
73 101 createSeries();
@@ -93,43 +121,61 void MainWidget::createSeries()
93 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 153 void MainWidget::detachLegend()
97 154 {
98 // Detach legend from chart and
99 // put legend to our custom scene
100 155 //![4]
101 156 QLegend *legend = m_chart->legend();
102 157 legend->detachFromChart();
103 legend->setGeometry(m_customView->rect());
104 m_customScene->addItem(legend);
158
159 m_chart->legend()->setBackgroundVisible(true);
160 m_chart->legend()->setBrush(QBrush(QColor(128,128,128,128)));
105 161 //![4]
106 162
107 // This forces redraw
108 QSize delta(1,1);
109 resize(size() + delta);
110 resize(size() - delta);
163 showLegendSpinbox();
164 updateLegendLayout();
165 update();
111 166 }
112 167
113 168
114 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 171 //![5]
120 172 QLegend *legend = m_chart->legend();
121
122 if (m_customScene->items().contains(legend)) {
123 m_customScene->removeItem(legend);
124 m_chartView->scene()->addItem(legend);
125 legend->attachToChart();
126 }
173 legend->attachToChart();
174 m_chart->legend()->setBackgroundVisible(false);
127 175 //![5]
128 176
129 // This forces redraw
130 QSize delta(1,1);
131 resize(size() + delta);
132 resize(size() - delta);
177 hideLegendSpinbox();
178 update();
133 179 }
134 180
135 181 void MainWidget::addBarset()
@@ -147,3 +193,32 void MainWidget::removeBarset()
147 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 28 #include <QGraphicsWidget>
29 29 #include <QGridLayout>
30 30 #include <QGraphicsGridLayout>
31 #include <QDoubleSpinBox>
32 #include <QGroupBox>
31 33
32 34 QTCOMMERCIALCHART_USE_NAMESPACE
33 35
@@ -36,9 +38,10 class MainWidget : public QWidget
36 38 Q_OBJECT
37 39 public:
38 40 explicit MainWidget(QWidget *parent = 0);
39
40 41 void createSeries();
41
42 void showLegendSpinbox();
43 void hideLegendSpinbox();
44
42 45 signals:
43 46
44 47 public slots:
@@ -47,6 +50,13 public slots:
47 50 void addBarset();
48 51 void removeBarset();
49 52
53 void setLegendLeft();
54 void setLegendRight();
55 void setLegendTop();
56 void setLegendBottom();
57
58 void updateLegendLayout();
59
50 60 private:
51 61
52 62 QChart *m_chart;
@@ -56,8 +66,12 private:
56 66 QGridLayout *m_mainLayout;
57 67 QGridLayout *m_buttonLayout;
58 68
59 QGraphicsView *m_customView;
60 QGraphicsScene *m_customScene;
69 // For detached layout
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 77 #endif // MAINWIDGET_H
@@ -318,8 +318,6 void ChartPresenter::updateLayout()
318 318 // recalculate legend position
319 319 if (legend != 0 && legend->isAttachedToChart() && legend->isEnabled()) {
320 320
321 QRect legendRect;
322
323 321 // Reserve some space for legend
324 322 switch (legend->alignment()) {
325 323
@@ -382,7 +380,9 void ChartPresenter::updateLayout()
382 380
383 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 387 if(m_chartRect!=chartRect && chartRect.isValid()){
388 388 m_chartRect=chartRect;
@@ -320,29 +320,38 QLegendPrivate::~QLegendPrivate()
320 320
321 321 void QLegendPrivate::setOffset(qreal x, qreal y)
322 322 {
323
323 bool scrollHorizontal = true;
324 324 switch(m_alignment) {
325
326 325 case Qt::AlignTop:
327 326 case Qt::AlignBottom: {
328 if(m_width<=m_rect.width()) return;
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 }
327 scrollHorizontal = true;
334 328 break;
335 329 }
336 330 case Qt::AlignLeft:
337 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 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
343 m_markers->setPos(m_rect.left(),-m_offsetY);
344 }
345 break;
342 if (scrollHorizontal) {
343 if(m_width<=m_rect.width()) return;
344
345 if (x != m_offsetX) {
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 360 void QLegendPrivate::updateLayout()
352 361 {
362 if (!m_attachedToChart) {
363 updateDetachedLayout();
364 return;
365 }
366
353 367 m_offsetX=0;
354 368 QList<QGraphicsItem *> items = m_markers->childItems();
355 369
@@ -406,8 +420,136 void QLegendPrivate::updateLayout()
406 420 break;
407 421 }
408 422
409 if (m_attachedToChart) {
410 m_presenter->updateLayout();
423 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 48 void setOffset(qreal x, qreal y);
49 49 void updateLayout();
50 void updateDetachedLayout();
50 51 void attachToChart();
51 52
52 53 public Q_SLOTS:
General Comments 0
You need to be logged in to leave comments. Login now