QML中绘图(1、Canvas 2、QPainter与QML结合)

 

QML中的Canvas和HTML5中Canvas是一样的,可以参考W3CSchool中的学习方法:HTML 5 Canvas 参考手册

 

画线、删除线、删除全部实例:

QML中绘图(1、Canvas 2、QPainter与QML结合)_第1张图片

 

不过,QML中的Canvas不够强大,画线会卡。我们用QPainter来实现画线,用QML来显示就好了,

方式如下:

1、先做好QPainter画线,做我们的类ALPaintedItem:

(1)头文件

#ifndef ALPAINTEDITEM_H
#define ALPAINTEDITEM_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
class ALPaintedItem : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth)
    Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)
    Q_PROPERTY(bool erasered READ isErasered WRITE setErasered)
public:
    ALPaintedItem(QQuickItem *parent = 0);
    ~ALPaintedItem();
    int penWidth() const { return m_penWidth; }
    void setPenWidth(int width) { m_penWidth = width; }
    QColor penColor() const { return m_brushColor; }
    void setPenColor(QColor color) { m_brushColor = color; }
    bool isErasered() const{ return m_bErasered; }
    void setErasered(bool erasered){ m_bErasered = erasered; }
    void paint(QPainter *painter);
    Q_INVOKABLE void init();
    Q_INVOKABLE void clear();
protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
private:
    void drawTmpLine();
    void drawBgLine(const QPainterPath &path);
    void drawPenStyle(QPainter *painter);
private:
    QImage m_bgImage;
    QImage m_tempImage;
    QColor m_brushColor;
    QColor m_eraserColor;
    QPointF m_nowPoint;
    QPointF m_lastPoint;
    QPainterPath *m_pDrawPath;
    int m_penWidth;
    bool m_bFlag;
    bool m_bErasered;
};

#endif // ALPAINTEDITEM_H

 

(2)源文件

#include "alpainteditem.h"
ALPaintedItem::ALPaintedItem(QQuickItem *parent)
    : QQuickPaintedItem(parent),
    m_brushColor(QColor(0, 0, 0 ,255)),
    m_eraserColor(QColor(255,255,255,255)),
    m_bFlag(true),
    m_bErasered(false),
    m_pDrawPath(NULL),
    m_penWidth(NULL)
{
    setAcceptedMouseButtons(Qt::LeftButton);
}

ALPaintedItem::~ALPaintedItem()
{
}

void ALPaintedItem::paint(QPainter *painter)
{
    if(m_bFlag)
        painter->drawImage(QRectF(0,0,m_bgImage.width(),m_bgImage.height()),m_bgImage);
    else
    {
        painter->drawImage(QRectF(0,0,m_tempImage.width(),m_tempImage.height()),m_tempImage);
        painter->drawImage(QRectF(0,0,m_bgImage.width(),m_bgImage.height()),m_bgImage);
    }
}

void ALPaintedItem::init()
{
    m_bgImage = QImage(this->width(),this->height(),QImage::Format_ARGB32);
    m_tempImage = QImage(this->width(),this->height(),QImage::Format_ARGB32);
    m_bgImage.fill(QColor(255,255,255,0));
    m_tempImage.fill(QColor(255,255,255,0));
}

void ALPaintedItem::clear()
{
    m_bgImage.fill(QColor(255,255,255,0));
    m_tempImage.fill(QColor(255,255,255,0));
    update();
}

void ALPaintedItem::mousePressEvent(QMouseEvent *event)
{
    if(!(event->button() & acceptedMouseButtons()))
    {
        QQuickPaintedItem::mousePressEvent(event);
    }
    else{
        if(m_pDrawPath == NULL)
        {
            m_pDrawPath = new QPainterPath();
        }
        m_pDrawPath->moveTo(event->localPos());
        m_nowPoint = event->localPos();
    }
}

void ALPaintedItem::mouseMoveEvent(QMouseEvent *event)
{
    m_lastPoint = m_nowPoint;
    m_nowPoint = event->localPos();
    QPointF tmpPoint = m_nowPoint - m_lastPoint;
    if(m_pDrawPath == NULL)
    {
        return;
    }
    if(qAbs(tmpPoint.x()) > 0 || qAbs(tmpPoint.y()) >0)
    {
        m_pDrawPath->quadTo(m_lastPoint.x() , m_lastPoint.y() ,(m_nowPoint.x() + m_lastPoint.x())/2,(m_nowPoint.y() + m_lastPoint.y())/2);
        m_bFlag = false;
        if(m_bErasered)
            drawBgLine(*m_pDrawPath);
        else
            drawTmpLine(); // 临时画
    }
    QQuickPaintedItem::mouseMoveEvent(event);
}

void ALPaintedItem::mouseReleaseEvent(QMouseEvent *event)
{
    if(!(event->button() & acceptedMouseButtons()))
    {
        QQuickPaintedItem::mousePressEvent(event);
    }
    else{
        if(m_pDrawPath != NULL)
        {
            m_bFlag = true;
            drawBgLine(*m_pDrawPath);
            delete m_pDrawPath;
            m_pDrawPath = NULL;
        }
    }
}

void ALPaintedItem::drawTmpLine()
{
    QPainter painter(&m_tempImage);
    drawPenStyle(&painter);
    painter.drawLine(m_lastPoint,m_nowPoint);
    qreal rad = this->width()/375.0*170;//点周围范围值
    qDebug() << "rad:" << rad;
    QRect rect = QRect(m_nowPoint.x() - 5, m_nowPoint.y() - 5,10,10);
    update(rect.adjusted(-rad,-rad,+rad,+rad));
}

void ALPaintedItem::drawBgLine(const QPainterPath &path)
{
    QPainter painter(&m_bgImage);
    drawPenStyle(&painter);
    painter.drawPath(path);
    m_tempImage.fill(QColor(255,255,255,0));
    update();
}

void ALPaintedItem::drawPenStyle(QPainter *painter)
{
    painter->setRenderHint(QPainter::Antialiasing);
    QBrush brush(m_brushColor, Qt::SolidPattern);
    if(m_bErasered)
    {
        painter->setCompositionMode(QPainter::CompositionMode_Clear);
        painter->setPen(QPen(brush, 5*m_penWidth, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin));
    }
    else
    {
        painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
        painter->setPen(QPen(brush, m_penWidth, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin));
    }
    painter->setBrush(Qt::NoBrush);
}

 

2、注册这个类

    qmlRegisterType("ALPaintedItem", 1, 0, "ALPaintedItem");

 

3、QML中调用

import QtQuick 2.5
import ALPaintedItem 1.0

Rectangle {
    id:photoMarkedRoot
    color: "transparent"
    property alias painter: painter

    Component.onCompleted: {
        painter.penWidth = initHeight/647.0*3
        painter.penColor = "red"
        painter.init()
    }

    ALPaintedItem {
        id: painter;
        width: photoMarkedRoot.width
        height: photoMarkedRoot.height
        onWidthChanged: {
            painter.init()
        }
        onHeightChanged: {
            painter.init()
        }
    }
}

 

你可能感兴趣的:(//C,C++,//Qt,QML)