能夠經過QT的重繪事件和鼠標事件來繪製多邊形,最簡單的辦法就是在繼承QWidget的窗體中重寫paintEvent、mousePressEvent等事件處理函數。QT提供了圖形繪製接口QPainter,經過該接口能夠繪製多種圖形,包括多邊形。this
新建一個基於QWidget的QT界面類GraphicsPainter,將其放置到想要顯示的窗體中。該類的具體代碼:spa
GraphicsPainter.h:.net
#ifndef GRAPHICSPAINTER_H #define GRAPHICSPAINTER_H #include <QWidget> class GraphicsPainter : public QWidget { Q_OBJECT public: explicit GraphicsPainter(QWidget *parent = nullptr); void SetDraw(bool bDraw); signals: void singalDrawOver(); public slots: protected: void paintEvent(QPaintEvent *); //繪製 void mousePressEvent(QMouseEvent *e); //按下 void mouseMoveEvent(QMouseEvent *e); //移動 void mouseReleaseEvent(QMouseEvent *e); //鬆開 void mouseDoubleClickEvent(QMouseEvent *event); //雙擊 bool bDraw; //是否處於繪製狀態 bool bLeftClick; //是否已經開始左鍵點擊,同時標識是否開始進行繪製 bool bMove; //是否處於繪製時的鼠標移動狀態 QVector<QPointF> pointList; QPointF movePoint; }; #endif // GRAPHICSPAINTER_H
GraphicsPainter.cpp:code
#include "graphicspainter.h" #include <QPainter> #include <QMouseEvent> #include <QDebug> GraphicsPainter::GraphicsPainter(QWidget *parent) : QWidget(parent) { //填充背景色 setAutoFillBackground(true); setBackgroundRole(QPalette::Base); bDraw = false; bLeftClick = false; bMove = false; setMouseTracking(true); } void GraphicsPainter::SetDraw(bool bDraw) { this->bDraw = bDraw; pointList.clear(); } //從新實現paintEvent void GraphicsPainter::paintEvent(QPaintEvent *) { QPainter painter(this); if(bDraw) { painter.setPen(QColor(255,0,0)); QVector<QLineF> lines; for(int i = 0; i<pointList.size()-1; i++) { QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y())); lines.push_back(line); } if(bMove&&pointList.size()>0) { QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint); lines.push_back(line); } painter.drawLines(lines); } } //按下 void GraphicsPainter::mousePressEvent(QMouseEvent *e) { if(bDraw) { if(!bLeftClick) { pointList.clear(); bLeftClick = true; } } //qDebug()<<"Press"; } //移動 void GraphicsPainter::mouseMoveEvent(QMouseEvent *e) { if(bDraw&&bLeftClick) { movePoint = e->pos(); bMove = true; this->update(); } //qDebug()<<"Move"; } //鬆開 void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e) { if(bDraw&&bLeftClick) { pointList.push_back(QPointF(e->x(), e->y())); bMove = false; this->update(); } //qDebug()<<"Release"; } //雙擊 void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event) { if(bDraw) { bLeftClick = false; pointList.push_back(pointList[0]); this->update(); singalDrawOver(); } //qDebug()<<"DoubleClick"; }
在從新實現的重繪事件中,經過QPainter繪製了一系列線組成線串,最後會首尾相連造成多邊形。這裏的bMove標識是否處於繪製時的鼠標移動狀態,只有鼠標左鍵點擊後纔會肯定爲真正的節點:blog
//從新實現paintEvent void GraphicsPainter::paintEvent(QPaintEvent *) { QPainter painter(this); if(bDraw) { painter.setPen(QColor(255,0,0)); QVector<QLineF> lines; for(int i = 0; i<pointList.size()-1; i++) { QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y())); lines.push_back(line); } if(bMove&&pointList.size()>0) { QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint); lines.push_back(line); } painter.drawLines(lines); } }
鼠標按下事件中,主要是經過bLeftClick值來肯定是否已經處於左鍵點擊狀態,同時還能標識是否開始進行繪製。一旦開始,就會把上次繪製的節點清除。繼承
//按下 void GraphicsPainter::mousePressEvent(QMouseEvent *e) { if(bDraw) { if(!bLeftClick) { pointList.clear(); bLeftClick = true; } } //qDebug()<<"Press"; }
一旦鼠標鬆開,就能夠肯定一個節點,此時須要調用update()進行重繪:接口
//鬆開 void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e) { if(bDraw&&bLeftClick) { pointList.push_back(QPointF(e->x(), e->y())); bMove = false; this->update(); } //qDebug()<<"Release"; }
當開始進行繪製後,移動鼠標就會處於繪製時的鼠標移動狀態,這時就會肯定bMove爲true,重繪事件就會將該鼠標點繪製出來,從而達到待選節點的效果:事件
//移動 void GraphicsPainter::mouseMoveEvent(QMouseEvent *e) { if(bDraw&&bLeftClick) { movePoint = e->pos(); bMove = true; this->update(); } //qDebug()<<"Move"; }
鼠標雙擊後,將第一個點加入到當前多邊形的節點中後,達到首尾相連的效果,此時就會結束繪製:ci
//雙擊 void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event) { if(bDraw) { bLeftClick = false; pointList.push_back(pointList[0]); this->update(); singalDrawOver(); } //qDebug()<<"DoubleClick"; }
這裏必定要注意,當進行雙擊操做時,首先會觸發一次mousePressEvent,而後觸發一次mouseReleaseEvent,接着纔會觸發一次mouseDoubleClickEvent,最後還會觸發一次mouseReleaseEvent。因此這就是這裏設置bLeftClick這個參數緣由:當觸發mouseDoubleClickEvent後,bLeftClick設置爲false,第二次觸發mouseReleaseEvent時內部就不會在作任何操做了。
最終運行的結果以下所示: