Qt实现绘制一个简单多边形的示例代码

发布时间:

可以通过QT的重绘事件和鼠标事件来绘制多边形,最简单的办法就是在继承QWidget的窗体中重写paintEvent、mousePressEvent等事件处理函数。QT提供了图形绘制接口QPainter,通过该接口可以绘制多种图形,包括多边形。

1. 实现

1.1 代码

新建一个基于QWidget的QT界面类GraphicsPainter,将其放置到想要显示的窗体中。该类的具体代码:

GraphicsPainter.h:

#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:

#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";
}

1.2 解析

在重新实现的重绘事件中,通过QPainter绘制了一系列线组成线串,最后会首尾相连形成多边形。这里的bMove标识是否处于绘制时的鼠标移动状态,只有鼠标左键点击后才会确定为真正的节点:

//重新实现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";
}

鼠标双击后,将第一个点加入到当前多边形的节点中后,达到首尾相连的效果,此时就会结束绘制:

//双击
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时内部就不会在做任何操作了。

1. 结果

最终运行的结果如下所示:

Qt实现绘制一个简单多边形的示例代码