mirror of https://github.com/qt/qtcharts.git
Scatter series marker visuals
This commit is contained in:
parent
c7a6b06985
commit
3f425cc482
|
@ -14,20 +14,38 @@ int main(int argc, char *argv[])
|
|||
// Create chart widget
|
||||
QChartView *chartWidget = new QChartView();
|
||||
|
||||
// Create scatter series with simple test data
|
||||
// Add scatter series with simple test data
|
||||
QScatterSeries *scatter = new QScatterSeries();
|
||||
*scatter << QPointF(0.5, 2.0)
|
||||
<< QPointF(1.0, 2.5)
|
||||
<< QPointF(1.5, 2.0)
|
||||
<< QPointF(2.0, 2.5);
|
||||
*scatter << QPointF(0.5, 5.0)
|
||||
<< QPointF(1.0, 4.5)
|
||||
<< QPointF(1.0, 5.5)
|
||||
<< QPointF(1.5, 5.0)
|
||||
<< QPointF(2.0, 4.5)
|
||||
<< QPointF(2.0, 5.5)
|
||||
<< QPointF(2.5, 5.0);
|
||||
chartWidget->addSeries(scatter);
|
||||
|
||||
// Add another scatter series with more complex data with random component
|
||||
// Add another scatter series
|
||||
// - more data with random component
|
||||
QScatterSeries *scatter2 = new QScatterSeries();
|
||||
for (qreal i(0.0); i < 20; i += 0.5)
|
||||
for (qreal i(0.0); i < 20; i += 0.05) {
|
||||
(*scatter2) << QPointF(i + (qreal)(rand() % 100) / 100.0,
|
||||
i + (qreal)(rand() % 100) / 100.0);
|
||||
i + (qreal)(rand() % 100) / 100.0);
|
||||
}
|
||||
chartWidget->addSeries(scatter2);
|
||||
// Custom pen and brush (not those defined by the chart theme)
|
||||
// - uses opaque color
|
||||
QColor color("#2685BF");
|
||||
color.setAlpha(80);
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
brush.setColor(color);
|
||||
scatter2->setMarkerBrush(brush);
|
||||
QPen pen;
|
||||
pen.setColor(color);
|
||||
pen.setWidth(2);
|
||||
scatter2->setMarkerPen(pen);
|
||||
// use a rectangle as the marker shape
|
||||
scatter2->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
|
||||
|
||||
// Use the chart widget as the central widget
|
||||
QMainWindow w;
|
||||
|
|
|
@ -127,9 +127,6 @@ void ChartPresenter::handleSeriesAdded(QChartSeries* series)
|
|||
QObject::connect(m_dataset, SIGNAL(domainChanged(const Domain&)),
|
||||
scatterPresenter, SLOT(handleDomainChanged(const Domain&)));
|
||||
m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
|
||||
// scatterSeries->d->m_theme = m_chartTheme->themeForSeries();
|
||||
// scatterSeries->d->setParentItem(this);
|
||||
// scatterSeries->d->m_boundingRect = m_rect.adjusted(margin(),margin(), -margin(), -margin());
|
||||
m_chartItems.insert(scatterSeries, scatterPresenter);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,14 @@ void ChartTheme::decorate(ChartItem* item, QChartSeries* series,int count)
|
|||
decorate(i,s,count);
|
||||
break;
|
||||
}
|
||||
case QChartSeries::SeriesTypeScatter: {
|
||||
QScatterSeries* s = qobject_cast<QScatterSeries*>(series);
|
||||
Q_ASSERT(s);
|
||||
ScatterPresenter* i = static_cast<ScatterPresenter*>(item);
|
||||
Q_ASSERT(i);
|
||||
decorate(i, s, count);
|
||||
break;
|
||||
}
|
||||
case QChartSeries::SeriesTypePie: {
|
||||
QPieSeries* s = static_cast<QPieSeries*>(series);
|
||||
PiePresenter* i = static_cast<PiePresenter*>(item);
|
||||
|
@ -179,16 +187,16 @@ void ChartTheme::decorate(ScatterPresenter* presenter, QScatterSeries* series, i
|
|||
Q_ASSERT(presenter);
|
||||
Q_ASSERT(series);
|
||||
|
||||
presenter->m_markerPen.setColor(m_seriesColor.at(count % m_seriesColor.size()));
|
||||
QColor color = m_seriesColor.at(count % m_seriesColor.size());
|
||||
// TODO: define alpha in the theme? or in the series?
|
||||
color.setAlpha(120);
|
||||
|
||||
// QPen pen;
|
||||
// if(pen != series->pen()){
|
||||
// item->setPen(series->pen());
|
||||
// return;
|
||||
// }
|
||||
// pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
|
||||
// pen.setWidthF(2);
|
||||
// item->setPen(pen);
|
||||
QBrush brush(color, Qt::SolidPattern);
|
||||
presenter->m_markerBrush = brush;
|
||||
|
||||
QPen pen(brush, 1);
|
||||
pen.setColor(color);
|
||||
presenter->m_markerPen = pen;
|
||||
}
|
||||
|
||||
void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/)
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
QTCOMMERCIALCHART_BEGIN_NAMESPACE
|
||||
|
||||
QScatterSeriesPrivate::QScatterSeriesPrivate() :
|
||||
m_data(QList<QPointF>())
|
||||
m_data(QList<QPointF>()),
|
||||
m_markerPen(QPen()),
|
||||
m_markerBrush(QBrush()),
|
||||
m_markerShape(QScatterSeries::MarkerShapeDefault)
|
||||
{
|
||||
// Initialize pen color to invalid to use a theme color by default
|
||||
m_markerPen.setColor(QColor::Invalid);
|
||||
m_markerBrush.setColor(QColor::Invalid);
|
||||
}
|
||||
|
||||
QScatterSeries::QScatterSeries(QObject *parent) :
|
||||
|
@ -54,6 +60,26 @@ QPen QScatterSeries::markerPen()
|
|||
return d->m_markerPen;
|
||||
}
|
||||
|
||||
void QScatterSeries::setMarkerBrush(QBrush brush)
|
||||
{
|
||||
d->m_markerBrush = brush;
|
||||
}
|
||||
|
||||
QBrush QScatterSeries::markerBrush()
|
||||
{
|
||||
return d->m_markerBrush;
|
||||
}
|
||||
|
||||
void QScatterSeries::setMarkerShape(MarkerShape shape)
|
||||
{
|
||||
d->m_markerShape = shape;
|
||||
}
|
||||
|
||||
QScatterSeries::MarkerShape QScatterSeries::markerShape()
|
||||
{
|
||||
return (QScatterSeries::MarkerShape) d->m_markerShape;
|
||||
}
|
||||
|
||||
#include "moc_qscatterseries.cpp"
|
||||
|
||||
QTCOMMERCIALCHART_END_NAMESPACE
|
||||
|
|
|
@ -11,8 +11,21 @@ class QScatterSeriesPrivate;
|
|||
class QTCOMMERCIALCHART_EXPORT QScatterSeries : public QChartSeries
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum MarkerShape {
|
||||
// TODO: to be defined by the graphics design
|
||||
// TODO: marker shapes: "x", star, rectangle, tilted rect, triangle, circle, dot
|
||||
MarkerShapeDefault = 0,
|
||||
MarkerShapePoint,
|
||||
MarkerShapeX,
|
||||
MarkerShapeRectangle,
|
||||
MarkerShapeTiltedRectangle,
|
||||
MarkerShapeTriangle,
|
||||
MarkerShapeCircle
|
||||
};
|
||||
|
||||
public:
|
||||
//QScatterSeries(QSeriesData *data, QObject *chart);
|
||||
QScatterSeries(QObject *parent = 0);
|
||||
~QScatterSeries();
|
||||
|
||||
|
@ -25,17 +38,20 @@ public:
|
|||
QScatterSeries& operator << (const QPointF &value);
|
||||
void setData(QList<QPointF> data);
|
||||
QList<QPointF> data();
|
||||
|
||||
//TODO? void insertData(int index, QPointF data);
|
||||
//TODO: insertData?
|
||||
|
||||
void setMarkerPen(QPen pen);
|
||||
QPen markerPen();
|
||||
// TODO: marker shapes: "x", star, rectangle, tilted rect, triangle, circle, dot
|
||||
//void setMarkerShape(MarkerShape shape);
|
||||
void setMarkerBrush(QBrush brush);
|
||||
QBrush markerBrush();
|
||||
void setMarkerShape(MarkerShape shape);
|
||||
MarkerShape markerShape();
|
||||
// TODO: marker size?
|
||||
|
||||
Q_SIGNALS:
|
||||
// TODO: move to PIMPL?
|
||||
// TODO: move to PIMPL for simplicity or does the user ever need these signals?
|
||||
// TODO: more finegrained signaling for performance reasons
|
||||
// (check QPieSeries implementation with change sets)
|
||||
void changed();
|
||||
|
||||
//public Q_SLOTS:
|
||||
|
|
|
@ -43,31 +43,48 @@ void ScatterPresenter::handleModelChanged()
|
|||
|
||||
void ScatterPresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
|
||||
{
|
||||
// TODO: The opacity should be user definable?
|
||||
//brush.setColor(QColor(255, 82, 0, 100));
|
||||
//if (m_series->markerPen().isValid()) {
|
||||
if (false) {
|
||||
QPen pen = painter->pen();
|
||||
QBrush brush = pen.brush();
|
||||
brush.setColor(m_series->markerPen().color());
|
||||
pen.setBrush(brush);
|
||||
pen.setWidth(4);
|
||||
painter->setPen(pen);
|
||||
}
|
||||
else {
|
||||
// TODO: fix this
|
||||
QPen pen = painter->pen();
|
||||
QBrush brush = pen.brush();
|
||||
brush.setColor(m_markerPen.color());
|
||||
pen.setBrush(brush);
|
||||
pen.setWidth(4);
|
||||
painter->setPen(pen);
|
||||
// TODO: Optimization: avoid setting on every paint method call?
|
||||
// The custom settings in series override those defined by the theme
|
||||
if (m_series->markerPen().color().isValid()) {
|
||||
painter->setPen(m_series->markerPen());
|
||||
painter->setBrush(m_series->markerBrush());
|
||||
} else {
|
||||
painter->setPen(m_markerPen);
|
||||
painter->setBrush(m_markerBrush);
|
||||
}
|
||||
|
||||
int shape = m_series->markerShape();
|
||||
|
||||
for (int i(0); i < m_scenex.count() && i < m_sceney.count(); i++) {
|
||||
if (scene()->width() > m_scenex.at(i) && scene()->height() > m_sceney.at(i))
|
||||
//painter->drawArc(m_scenex.at(i), m_sceney.at(i), 2, 2, 0, 5760);
|
||||
painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
|
||||
// Paint a shape
|
||||
switch (shape) {
|
||||
case QScatterSeries::MarkerShapeDefault:
|
||||
// Fallthrough, defaults to circle
|
||||
case QScatterSeries::MarkerShapeCircle:
|
||||
painter->drawChord(m_scenex.at(i), m_sceney.at(i), 9, 9, 0, 5760);
|
||||
break;
|
||||
case QScatterSeries::MarkerShapePoint:
|
||||
painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
|
||||
break;
|
||||
case QScatterSeries::MarkerShapeRectangle:
|
||||
painter->drawRect(m_scenex.at(i), m_sceney.at(i), 9, 9);
|
||||
break;
|
||||
case QScatterSeries::MarkerShapeTiltedRectangle:
|
||||
// TODO:
|
||||
static const QPointF points[4] = {
|
||||
QPointF(-1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
|
||||
QPointF(0.0 + m_scenex.at(i), 1.0 + m_sceney.at(i)),
|
||||
QPointF(1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
|
||||
QPointF(0.0 + m_scenex.at(i), -1.0 + m_sceney.at(i))
|
||||
};
|
||||
painter->drawPolygon(points, 4);
|
||||
break;
|
||||
default:
|
||||
// TODO: implement the rest of the shapes
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
QList<qreal> m_sceney;
|
||||
Domain m_visibleChartArea;
|
||||
QPen m_markerPen;
|
||||
QBrush m_markerBrush;
|
||||
};
|
||||
|
||||
QTCOMMERCIALCHART_END_NAMESPACE
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
public:
|
||||
QList<QPointF> m_data;
|
||||
QPen m_markerPen;
|
||||
QBrush m_markerBrush;
|
||||
int m_markerShape;
|
||||
};
|
||||
|
||||
QTCOMMERCIALCHART_END_NAMESPACE
|
||||
|
|
Loading…
Reference in New Issue