Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

free hand draw in qgraphicsview

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);
like image 206
Wagmare Avatar asked Dec 03 '25 12:12

Wagmare


2 Answers

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);
} 
like image 52
Wagmare Avatar answered Dec 05 '25 01:12

Wagmare


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.

like image 29
Grant Carthew Avatar answered Dec 05 '25 02:12

Grant Carthew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!