Qt通过鼠标绘制线条、矩形、多边形本质都是根据鼠标的坐标位移,使用QPainter的自带的函数进行绘制。
QGraphicsView三件套事件传递机制:
具体代码开箱即用:
view.h
#include <QObject>
#include <QGraphicsView>
#include <QVector>
class GSELTestGraphicsScence;
class GSELTestGraphicsView : public QGraphicsView
{
Q_OBJECT
Q_PROPERTY(QRect viewRect MEMBER m_viewRect READ GetRect WRITE SetRect NOTIFY viewRectChanged)
public:
explicit GSELTestGraphicsView(QWidget *parent = Q_NULLPTR);
~GSELTestGraphicsView() override;
protected:
//void paintEvent(QPaintEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
signals:
void viewRectChanged(QRect rect);
public:
void OnInitView();
void OnUnInitView();
void SetRect(QRect rect);
QRect GetRect()const;
private:
QRect m_viewRect;
};
view.cpp
GSELTestGraphicsView::GSELTestGraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
OnInitView();
}
GSELTestGraphicsView::~GSELTestGraphicsView()
{
OnUnInitView();
}
void GSELTestGraphicsView::mousePressEvent(QMouseEvent* event)
{
qDebug() << "GraphicsView: mousePressEvent " << event->pos();
if (event->buttons() & Qt::LeftButton)
{
//m_point_pos.emplace_back(event->pos());
}
QGraphicsView::mousePressEvent(event);
}
void GSELTestGraphicsView::mouseMoveEvent(QMouseEvent* event)
{
// qDebug() << "GraphicsView: mouseMoveEvent " << event->pos();
QGraphicsView::mouseMoveEvent(event);
}
void GSELTestGraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
qDebug() << "GraphicsView: mouseReleaseEvent " << event->pos();
this->update();
QGraphicsView::mouseReleaseEvent(event);
}
void GSELTestGraphicsView::wheelEvent(QWheelEvent* event)
{
QGraphicsView::wheelEvent(event);
}
void GSELTestGraphicsView::OnInitView()
{
}
void GSELTestGraphicsView::OnUnInitView()
{
}
void GSELTestGraphicsView::SetRect(QRect rect)
{
m_viewRect = rect;
emit viewRectChanged(rect);
}
QRect GSELTestGraphicsView::GetRect() const
{
return m_viewRect;
}
Sence.h
#include <QGraphicsScene>
class GSELTestGraphicsScence : public QGraphicsScene
{
Q_OBJECT
public:
explicit GSELTestGraphicsScence(QObject *parent = Q_NULLPTR);
~GSELTestGraphicsScence()override;
public:
void OnInitSence();
void OnUnInitSence();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent* event)override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* event)override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)override;
void wheelEvent(QGraphicsSceneWheelEvent* event)override;
signals:
private:
};
Sence.h
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
GSELTestGraphicsScence::GSELTestGraphicsScence(QObject*parent)
: QGraphicsScene(parent)
{
OnInitSence();
}
GSELTestGraphicsScence::~GSELTestGraphicsScence()
{
OnUnInitSence();
}
void GSELTestGraphicsScence::OnInitSence()
{
clearFocus();
}
void GSELTestGraphicsScence::OnUnInitSence()
{
}
void GSELTestGraphicsScence::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
qDebug() << "GraphicsScence: mousePressEvent " << event->pos();
QGraphicsScene::mousePressEvent(event);
}
void GSELTestGraphicsScence::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
//qDebug() << "GraphicsScence: mouseMoveEvent " << event->pos();
QGraphicsScene::mouseMoveEvent(event);
}
void GSELTestGraphicsScence::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
qDebug() << "GraphicsScence: mouseReleaseEvent " << event->pos();
QGraphicsScene::mouseReleaseEvent(event);
}
void GSELTestGraphicsScence::wheelEvent(QGraphicsSceneWheelEvent* event)
{
QGraphicsScene::wheelEvent(event);
}
Item.h
#include <QGraphicsItem>
#include <QPainter>
#include <QVector>
#include <array>
#include <QPointF>
#include <QPixmap>
#include "GSDrawShap.h"
class GSELTestGraphicsItem : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
explicit GSELTestGraphicsItem(QObject* parent = nullptr);
~GSELTestGraphicsItem() override;
public:
void OnInitItem();
void OnUnInitItem();
protected:
QRectF boundingRect() const override;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = Q_NULLPTR)override;
void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
void wheelEvent(QGraphicsSceneWheelEvent* event) override;
public slots:
private:
GSDraw::DrawType m_draw_type;
GSDrawShap* m_draw_shap;
GSDrawShap* m_draw_img_shap;
QVector<QPointF> m_point_pos;
QPointF m_start_pos;
QPointF m_end_pos;
};
Item.h
#include "GSELTestGraphicsItem.h"
#include "GSELTestCommon.h"
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QScreen>
#include <QGuiApplication>
#include <QCursor>
GSELTestGraphicsItem::GSELTestGraphicsItem(QObject* parent):QObject(parent), QGraphicsItem()
{
setFlag(QGraphicsItem::ItemIsFocusable);
//setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
this->setAcceptHoverEvents(true);
m_draw_shap =new GSDrawShap(nullptr);
m_draw_img_shap = new GSDrawShap(nullptr);
m_draw_img_shap->SetDrawType(GSDraw::DrawType::image);
m_draw_type = GSDraw::DrawType::rect;
m_draw_shap->SetDrawType(m_draw_type);
}
GSELTestGraphicsItem::~GSELTestGraphicsItem()
{
}
void GSELTestGraphicsItem::OnInitItem()
{
}
void GSELTestGraphicsItem::OnUnInitItem()
{
}
QRectF GSELTestGraphicsItem::boundingRect() const
{
QScreen* screen = QGuiApplication::primaryScreen();
int viewWidth = screen->geometry().width() / 2;
int viewHeight = screen->geometry().height();
return QRectF(0, 0, viewWidth, viewHeight);
}
void GSELTestGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
m_draw_img_shap->paint(*painter);
m_draw_shap->paint(*painter);
}
void GSELTestGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
qDebug() << "GSELTestGraphicsItem: mousePressEvent " << event->pos();
setFocus();
//setCursor(Qt::ClosedHandCursor);
//this->boundingRect().contains(event->pos())
if (event->button() & Qt::LeftButton)
{
if (m_draw_type == GSDraw::DrawType::rect)
{
QPointF startPos = event->pos();
QPointF endPos = event->pos();
m_draw_shap->SetStartPos(startPos);
m_draw_shap->SetEndPos(endPos);
}
else if (m_draw_type == GSDraw::DrawType::point)
{
QPointF startPos = event->pos();
QPointF endPos = event->pos();
m_draw_shap->SetStartPos(startPos);
m_draw_shap->SetEndPos(endPos);
}
}
QGraphicsItem::mousePressEvent(event);
}
void GSELTestGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (m_draw_type == GSDraw::DrawType::rect)
{
QPointF endPos = event->pos();
m_draw_shap->SetEndPos(endPos);
update(QRectF(m_start_pos, m_end_pos));
}
QGraphicsItem::mouseMoveEvent(event);
}
void GSELTestGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
qDebug() << "GSELTestGraphicsItem: mouseReleaseEvent " << event->pos();
if (event->button() & Qt::LeftButton)
{
if (m_draw_type == GSDraw::DrawType::rect)
{
}
else if (m_draw_type == GSDraw::DrawType::point)
{
QPointF endPos = event->pos();
m_draw_shap->SetEndPos(endPos);
update(endPos.x() - 5, endPos.y(), 10, 1);
update(endPos.x(), endPos.y() - 5, 1, 10);
}
}
QGraphicsItem::mouseReleaseEvent(event);
}
void GSELTestGraphicsItem::wheelEvent(QGraphicsSceneWheelEvent* event)
{
QGraphicsItem::wheelEvent(event);
}
绘制事件用到的类
GSDraw、GSDrawImage、GSDrawPoints、GSDrawRectangle、GSDrawShap
#include <QObject>
#include <QPainter>
#include <QPoint>
#include <QPointF>
class GSDraw : public QObject
{
Q_OBJECT
public:
GSDraw(QObject *parent);
~GSDraw();
public:
enum class DrawType {rect=0,point,line,image};
public:
void SetPainter(QPainter, DrawType);
void SetStartPos(QPoint&);
void SetStartPos(QPointF&);
void SetEndPos(QPoint&);
void SetEndPos(QPointF&);
void ClearPoints();
virtual void paint(QPainter& painter);
protected:
DrawType m_draw_type;
QPoint m_start_pos;
QPoint m_end_pos;
QPointF m_start_pos_f;
QPointF m_end_pos_f;
QVector<QPoint> pointList;
QVector<QPointF> pointfList;
};
#include "GSDraw.h"
GSDraw::GSDraw(QObject *parent)
: QObject(parent)
{}
GSDraw::~GSDraw()
{}
void GSDraw::SetPainter(QPainter painter, DrawType type)
{
m_draw_type = type;
}
void GSDraw::SetStartPos(QPoint& pos)
{
m_start_pos = pos;
}
void GSDraw::SetStartPos(QPointF& pos)
{
m_start_pos_f = pos;
pointfList.push_back(pos);
}
void GSDraw::SetEndPos(QPoint& pos)
{
m_end_pos = pos;
}
void GSDraw::SetEndPos(QPointF& pos)
{
m_end_pos_f = pos;
pointfList.push_back(pos);
}
void GSDraw::ClearPoints()
{
pointfList.clear();
}
void GSDraw::paint(QPainter& painter)
{
}
#include <QObject>
#include "GSDraw.h"
class GSDrawPoints : public GSDraw
{
Q_OBJECT
public:
GSDrawPoints(QObject *parent = nullptr);
~GSDrawPoints();
public:
void paint(QPainter& painter) override;
};
#include "GSDrawPoints.h"
GSDrawPoints::GSDrawPoints(QObject *parent)
: GSDraw(parent)
{}
GSDrawPoints::~GSDrawPoints()
{}
void GSDrawPoints::paint(QPainter & painter)
{
painter.save();
QPen pen;
pen.setWidth(3);
pen.setColor(QColor(255, 0, 0));
painter.setPen(pen);
for (auto point : pointfList)
{
painter.drawLine(point.x() - 5, point.y(), point.x() + 5, point.y());
painter.drawLine(point.x(), point.y() + 5, point.x(), point.y() - 5);
}
painter.restore();
}
#include <QObject>
#include "GSDraw.h"
class GSDrawRectangle : public GSDraw
{
Q_OBJECT
public:
GSDrawRectangle(QObject *parent = nullptr);
~GSDrawRectangle();
public:
void paint(QPainter& painter) override;
};
#include "GSDrawRectangle.h"
#include <QRectF>
GSDrawRectangle::GSDrawRectangle(QObject *parent)
: GSDraw(parent)
{}
GSDrawRectangle::~GSDrawRectangle()
{}
void GSDrawRectangle::paint(QPainter & painter)
{
painter.save();
QPen pen;
pen.setWidth(3);
pen.setColor(QColor(255, 0, 0));
painter.setPen(pen);
painter.drawRect(QRectF(m_start_pos_f, m_end_pos_f));
painter.restore();
}
#include <QObject>
#include "GSDraw.h"
class GSDrawImage : public GSDraw
{
Q_OBJECT
public:
GSDrawImage(QObject *parent = nullptr);
~GSDrawImage();
public:
void paint(QPainter& painter) override;
};
#include "GSDrawImage.h"
#include <QScreen>
#include <QGuiApplication>
GSDrawImage::GSDrawImage(QObject *parent)
: GSDraw(parent)
{}
GSDrawImage::~GSDrawImage()
{}
void GSDrawImage::paint(QPainter & painter)
{
QPixmap pix;
pix.load(":/image/img1.jpg");
int imgW = 480;
int imgH = 640;
QScreen* screen = QGuiApplication::primaryScreen();
int viewWidth = screen->geometry().width() / 2;
int viewHeight = screen->geometry().height();
int leftTopX = (viewWidth - imgW) / 2;
int leftTopY = (viewHeight - imgH) / 2;
painter.drawPixmap(QRect(leftTopX, leftTopY, imgW, imgH), pix);
}
#include <QObject>
#include <QPainter>
#include "GSDraw.h"
class GSDrawShap : public QObject
{
Q_OBJECT
public:
GSDrawShap(QObject *parent);
~GSDrawShap();
public:
void SetDrawType(GSDraw::DrawType);
void SetPainter(QPainter, GSDraw::DrawType);
void SetStartPos(QPoint&);
void SetStartPos(QPointF&);
void SetEndPos(QPoint&);
void SetEndPos(QPointF&);
void paint(QPainter& painter);
void ClearPoints();
private:
GSDraw* m_draw_obj;
GSDraw::DrawType m_draw_type;
};
#include "GSDrawShap.h"
#include "GSDrawImage.h"
#include "GSDrawPoints.h"
#include "GSDrawRectangle.h"
GSDrawShap::GSDrawShap(QObject *parent)
: QObject(parent)
{}
GSDrawShap::~GSDrawShap()
{}
void GSDrawShap::SetDrawType(GSDraw::DrawType type)
{
m_draw_type = type;
switch (type)
{
case GSDraw::DrawType::line:
break;
case GSDraw::DrawType::rect:
m_draw_obj = new GSDrawRectangle();
break;
case GSDraw::DrawType::point:
m_draw_obj = new GSDrawPoints();
break;
case GSDraw::DrawType::image:
m_draw_obj = new GSDrawImage();
break;
default:
break;
}
}
void GSDrawShap::SetPainter(QPainter, GSDraw::DrawType)
{
}
void GSDrawShap::SetStartPos(QPoint& pos)
{
m_draw_obj->SetStartPos(pos);
}
void GSDrawShap::SetStartPos(QPointF& pos)
{
m_draw_obj->SetStartPos(pos);
}
void GSDrawShap::SetEndPos(QPoint& pos)
{
m_draw_obj->SetEndPos(pos);
}
void GSDrawShap::SetEndPos(QPointF& pos)
{
m_draw_obj->SetEndPos(pos);
}
void GSDrawShap::paint(QPainter& painter)
{
m_draw_obj->paint(painter);
}
void GSDrawShap::ClearPoints()
{
m_draw_obj->ClearPoints();
}
具体的使用方法
QScreen* screen = QGuiApplication::primaryScreen();
int viewWidth = screen->geometry().width() / 2;
int viewHeight = screen->geometry().height();
m_elScence = new GSELTestGraphicsScence();
m_elScence->setSceneRect(QRect(0, 0, viewWidth - 2, viewHeight - 2));
GSELTestGraphicsItem* item = new GSELTestGraphicsItem();
//item->setFlag(QGraphicsItem::ItemIgnoresTransformations);//设置放大view,不影响item的大小,但是item的位置改变了
m_elScence->addItem(item);
m_elImgView = new GSELTestGraphicsView();
ui->horizontalLayout_2->addWidget(m_elImgView);
m_elImgView->setFixedSize(QSize(viewWidth, viewHeight));
m_elImgView->setProperty("viewRect", QVariant::fromValue(QRect(0, 0, viewWidth, viewHeight)));
m_elImgView->setScene(m_elScence);