i have gone through the scribble example for how to draw free form . i want the same free form draw using QGraphicsitem on qgraphicsview. i should draw it as a graphicsitem as i can move the selected free form every where in the scene. i tried this
DrawnPathItem = this->scene()->addPath(QPainterPath());
QGraphicsLineItem liner;
liner.setLine( QLineF(startPoint, endPoint) );
liner.setPen(QPen(Qt::red));
QPainterPath path = DrawnPathItem->path();
path.setFillRule(Qt::WindingFill);
path.addPath( liner.shape() );
path = path.simplified();
DrawnPathItem->setPath(path);
i did it using
void mousePressEvent(QGraphicsSceneMouseEvent *event)
{
myPath = new QGraphicsPathItem();
previous = event->scenePos();
QPainterPath p;
p.moveTo(previous);
myPath->setPath(p);
this->addItem(myPath);
}
void ::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(myPath)
{
QPainterPath path = myPath->path();
previous = event->scenePos();
path.lineTo(previous);
myPath->setPath(path);
}
I'm adding to the answer above because there is limited resources on the internet that show this technique using the QGraphicsPathItem.
Starting with the FreeDraw header file:
#pragma once
#include "item.hpp"
#include <QGraphicsPathItem>
class FreeDraw : public QGraphicsPathItem {
public:
FreeDraw(Item::DrawKit drawKit, QGraphicsItem *parent = nullptr);
qreal getLineWidth();
void setLineWidth(qreal width);
QColor getLineColor();
void setLineColor(QColor color);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr) override;
private:
Item::Mode _mode = Item::Mode::INITIAL_DRAW;
QPointF _anchor;
};
The Item namespace:
#pragma once
#include <QPointF>
#include <QColor>
namespace Item {
enum class Mode {
IDLE,
INITIAL_DRAW
};
struct DrawKit {
QPointF anchorPoint;
QColor color;
qreal lineWidth;
bool fill;
};
}
And lastly the code file:
#include "freedraw.hpp"
#include "item.hpp"
#include <QPainter>
#include <QPen>
#include <QtMath>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
FreeDraw::FreeDraw(Item::DrawKit drawKit, QGraphicsItem *parent)
: QGraphicsPathItem(parent) {
qDebug() << "[FreeDraw][constructor] drawKit: " << &drawKit;
setPos(drawKit.anchorPoint);
QPen pen = QPen(drawKit.color);
pen.setWidth(drawKit.lineWidth);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
setPen(pen);
// Prevents the path from closing
setBrush(QBrush(Qt::transparent));
// We need to draw at least a pixel for mouseMoveEvents to register
QPainterPath p;
p.moveTo(0,0);
p.lineTo(1,1);
setPath(p);
}
void FreeDraw::setLineColor(QColor color) {
QPen changePen = pen();
changePen.setColor(color);
setPen(changePen);
}
void FreeDraw::setLineWidth(qreal width) {
QPen changePen = pen();
changePen.setWidth(width);
setPen(changePen);
}
void FreeDraw::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) {
// The following lines prevent the QGraphicsPathItem from drawing the items rectangle outline
QStyleOptionGraphicsItem newOption(*option);
newOption.state &= ~QStyle::State_Selected;
QGraphicsPathItem::paint(painter, &newOption, widget);
}
void FreeDraw::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QGraphicsPathItem::mousePressEvent(event);
}
void FreeDraw::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
if (_mode == Item::Mode::INITIAL_DRAW) {
// Copy the QGraphicsPathItems path, change it, and give it back
QPainterPath newPath = path();
newPath.moveTo(event->lastPos());
newPath.lineTo(event->pos());
setPath(newPath);
}
QGraphicsPathItem::mouseMoveEvent(event);
}
void FreeDraw::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
_mode = Item::Mode::IDLE;
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
QGraphicsPathItem::mouseReleaseEvent(event);
}
Finally, you will have to add this to the QGraphicsScene with an addItem() call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With