Qt通过鼠标绘制线条、矩形、多边形本质都是根据鼠标的坐标位移,使用QPainter的自带的函数进行绘制。
QGraphicsView三件套事件传递机制:
具体代码开箱即用:
view.h
#include #include #include 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 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 #include #include 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 #include #include #include #include #include #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 m_point_pos; QPointF m_start_pos; QPointF m_end_pos; };
Item.h
#include "GSELTestGraphicsItem.h" #include "GSELTestCommon.h" #include #include #include #include #include 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 #include #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 "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 #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 #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 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 #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 #include 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 #include #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);