在QT中要实现一个涂鸦窗口是非常简单的事情,先将项目早期用到的涂鸦窗口抽取出来做成一个通用的模型,方便以后的项目中可以使用。
效果图:
实现功能:
1、鼠标按住随意划线;
2、可设置线宽,样式,颜色;
3、可设置背景图片;
4、可清除所有绘制;
5、可保存涂鸦图片。
涂鸦窗口类头文件实现:
#ifndef DOODLEWIDGET_H
#define DOODLEWIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QIODevice>
class DoodleWidgetPrivate;
class DoodleWidget : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE(DoodleWidget)
public:
explicit DoodleWidget(QWidget *parent = 0, const QSize& doodleSize = QSize(800, 600));
virtual ~DoodleWidget();
// set background image
bool setBackgroundImage(const QString& path, bool bStretch = false);
//save cache image to file / device IO
bool saveImage(const QString& path, const QString& ext = "JPEG");
bool saveImage(QIODevice* device, const QString& ext = "JPEG");
//set cache image size
void setDoodleSize(const QSize& size);
//set pen width,color,style
void setPenStyle(int width = 3, Qt::PenStyle ps = Qt::SolidLine, const QColor& qc = Qt::black);
signals:
public slots:
void changePenWidth(int width);
void changePenStyle(Qt::PenStyle ps);
void changePenColor(const QColor& cr);
void clearDoodle();
protected:
void paintEvent(QPaintEvent* event);
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
private:
DoodleWidgetPrivate* d_ptr = nullptr;
};
#endif // DoodleWIDGET_H
涂鸦窗口实现文件:
#include "doodlewidget.h"
#include <QPainter>
class DoodleWidgetPrivate
{
Q_DECLARE_PUBLIC(DoodleWidget)
public:
DoodleWidgetPrivate(DoodleWidget* q, const QSize& doodleSize);
~DoodleWidgetPrivate();
void initCache();
void drawLines(const QPoint& ptBegin, const QPoint& ptEnd);
public:
DoodleWidget* q_ptr = nullptr;
QPixmap* image = nullptr;
QPainter* painter = nullptr;
QPen pen;
QPoint lastCursorPos;
bool bLeftMousePressed = false;
};
DoodleWidgetPrivate::DoodleWidgetPrivate(DoodleWidget* q, const QSize& doodleSize)
: q_ptr(q), image(new QPixmap(doodleSize)), painter(new QPainter(image))
{
painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
initCache();
}
DoodleWidgetPrivate::~DoodleWidgetPrivate()
{
delete painter;
delete image;
}
void DoodleWidgetPrivate::initCache()
{
Q_Q(DoodleWidget);
painter->fillRect(0, 0, image->width(), image->height(), Qt::white);
q->update();
}
void DoodleWidgetPrivate::drawLines(const QPoint &ptBegin, const QPoint &ptEnd)
{
Q_Q(DoodleWidget);
painter->drawLine(ptBegin, ptEnd);
q->update();
}
DoodleWidget::DoodleWidget(QWidget *parent, const QSize &doodleSize)
: QWidget(parent), d_ptr(new DoodleWidgetPrivate(this, doodleSize))
{
setCursor(Qt::CrossCursor);
setMouseTracking(true);
setPenStyle();
}
DoodleWidget::~DoodleWidget()
{
delete d_ptr;
}
bool DoodleWidget::setBackgroundImage(const QString &path, bool bStretch)
{
Q_D(DoodleWidget);
QPixmap tmp;
if (!tmp.load(path)) {
return false;
}
if (bStretch) {
d->painter->drawPixmap(0, 0, d->image->width(), d->image->height(), tmp);
}
else {
d->painter->drawPixmap(0, 0, tmp);
}
return true;
}
bool DoodleWidget::saveImage(const QString &path, const QString &ext)
{
Q_D(DoodleWidget);
return d->image->save(path,