How to draw triangle points in QtChart?
-
wrote on 15 Nov 2017, 03:54 last edited by
Hello everyone,
I want to draw some points with triangle symbol, but the marker shape only support circle and rectangle shape.
I can create a triangle shape as QImage and send it to the QBrush of QScatterSeries, but if I want to draw I border, I still can only draw a circular or rectangular border.
Is there anyway I can draw a triangle point with triangle border?
-
-
wrote on 16 Nov 2017, 02:44 last edited by
@SGaist Hi SGaist, Thank you for your answering.
Maybe I didn't make it clear, I want to draw some triangles with border, and others without border, so I have to use setBorderColor or set Pen of QScatterSeries to add the border in some cases. -
-
What did you modify ?
-
wrote on 17 Nov 2017, 04:28 last edited by
@NeeMoo ,
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
QPen pen;
pen.setWidth(4);
pen.setColor(Qt::red);
painter.setBrush(Qt::blue);
painter.setPen(pen);
QPointF *points = new QPointF[3];
points[0] = QPointF(100,50);
points[1] = QPointF(50,150);
points[2] = QPointF(150,150);
painter.drawPolygon(points,3);
} -
wrote on 19 Nov 2017, 18:30 last edited by
@SGaist I rewrited the ScatterChartItem and ScatterSeries, added a TriangleMarker:
void ScatterChartItem::createPoints(int count)
{
for (int i = 0; i < count; ++i) {QGraphicsItem *item = 0; switch (m_shape) { case QScatterSeries::MarkerShapeCircle: { item = new CircleMarker(0, 0, m_size, m_size, this); const QRectF &rect = item->boundingRect(); item->setPos(-rect.width() / 2, -rect.height() / 2); break; } case QScatterSeries::MarkerShapeRectangle: item = new RectangleMarker(0, 0, m_size, m_size, this); item->setPos(-m_size / 2, -m_size / 2); break; case QScatterSeries::MarkerShapeTriangle: item = new TriangleMarker(0, 0, m_size, m_size, this); item->setPos(-m_size / 2, -m_size / 2); default: qWarning() << "Unsupported marker type"; break; } m_items.addToGroup(item); }
}
class TriangleMarker : public QGraphicsPolygonItem
{public:
TriangleMarker(qreal x, qreal y, qreal w, qreal h, ScatterChartItem *parent)
: QGraphicsPolygonItem(QPolygonF() << QPointF(x, y + h) << QPointF(x + w, y + h) << QPointF(x + w / 2.0f, y), parent),
m_parent(parent)
{
setAcceptHoverEvents(true);
setFlag(QGraphicsItem::ItemIsSelectable);
}protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mousePressEvent(event);
m_parent->markerPressed(this);
m_parent->setMousePressed();
}
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsPolygonItem::hoverEnterEvent(event);
m_parent->markerHovered(this, true);
}
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsPolygonItem::hoverLeaveEvent(event);
m_parent->markerHovered(this, false);
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mouseReleaseEvent(event);
m_parent->markerReleased(this);
if (m_parent->mousePressed())
m_parent->markerSelected(this);
m_parent->setMousePressed(false);
}
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mouseDoubleClickEvent(event);
m_parent->markerDoubleClicked(this);
}private:
ScatterChartItem *m_parent;
};But the legend of that maker shape is not correct, so it should have a little work on legend.
-
Nice !
Did you consider contributing your changes ?
-
wrote on 25 Nov 2017, 15:45 last edited by
Yeah of course! But I don't know how to contribute my code, I'm a beginner of programming, haha, could you give me some advice?
-
Sure, the starting point is here. Take your time to go through it. The first time setup might take some time but following the documentation it's not that complicated.
-
@SGaist I rewrited the ScatterChartItem and ScatterSeries, added a TriangleMarker:
void ScatterChartItem::createPoints(int count)
{
for (int i = 0; i < count; ++i) {QGraphicsItem *item = 0; switch (m_shape) { case QScatterSeries::MarkerShapeCircle: { item = new CircleMarker(0, 0, m_size, m_size, this); const QRectF &rect = item->boundingRect(); item->setPos(-rect.width() / 2, -rect.height() / 2); break; } case QScatterSeries::MarkerShapeRectangle: item = new RectangleMarker(0, 0, m_size, m_size, this); item->setPos(-m_size / 2, -m_size / 2); break; case QScatterSeries::MarkerShapeTriangle: item = new TriangleMarker(0, 0, m_size, m_size, this); item->setPos(-m_size / 2, -m_size / 2); default: qWarning() << "Unsupported marker type"; break; } m_items.addToGroup(item); }
}
class TriangleMarker : public QGraphicsPolygonItem
{public:
TriangleMarker(qreal x, qreal y, qreal w, qreal h, ScatterChartItem *parent)
: QGraphicsPolygonItem(QPolygonF() << QPointF(x, y + h) << QPointF(x + w, y + h) << QPointF(x + w / 2.0f, y), parent),
m_parent(parent)
{
setAcceptHoverEvents(true);
setFlag(QGraphicsItem::ItemIsSelectable);
}protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mousePressEvent(event);
m_parent->markerPressed(this);
m_parent->setMousePressed();
}
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsPolygonItem::hoverEnterEvent(event);
m_parent->markerHovered(this, true);
}
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsPolygonItem::hoverLeaveEvent(event);
m_parent->markerHovered(this, false);
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mouseReleaseEvent(event);
m_parent->markerReleased(this);
if (m_parent->mousePressed())
m_parent->markerSelected(this);
m_parent->setMousePressed(false);
}
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsPolygonItem::mouseDoubleClickEvent(event);
m_parent->markerDoubleClicked(this);
}private:
ScatterChartItem *m_parent;
};But the legend of that maker shape is not correct, so it should have a little work on legend.
wrote on 23 Sept 2022, 13:28 last edited by@NeeMoo Nice! I'm also a beginner right now, so could you explain where exactly the data-point is in relation to the triangle? If I'm interpreting your code right, I think it's in the bottom left corner?
Because I would like to have two kinds of TriangleMarker, one pointing up with the data-point at the top corner and one pointing down with the data-point at the bottom corner. To do that I would just have to make two TriangleMarker classes and change the 3 QPoints that make up the QPolygonF, right?