展示效果
功能实现
想要实现鼠标拖拽绘图的效果,离不开鼠标的三大事件:按下、移动、释放
那么具体实现实时绘制矩形框的核心流程是什么呢?
第一步:鼠标左键点击,记录初始点击位置
第二步:在窗口中移动鼠标,实时获取鼠标拖动点,根据拖动点绘制指定形状
第三步:鼠标点击右键释放鼠标,绘制最终图形
描述的实现流程很简单,那么,接下来就实际操作吧!
在进行鼠标点击绘制的时候,为了兼容多个图形的实时绘制,这里,不只是用两个QPoint成员变量记录鼠标点,而是采取了vector<QPontF>容器存储的方式。
例如:三角形图形,需要三个点才能确定图形;曲线图形,是由N多个点才能确定图形;等等。。。
所以说,这里采用了vector容器进行数据存储,任何图形的点都可以进行存储。
所有的图形枚举类型,如下表格:
枚举类型 |
形状 |
Drawing_Normal |
无图形绘制 |
Drawing_Circular |
圆形 |
Drawing_StraightLine |
直线 |
Drawing_Rectangular |
矩形 |
Drawing_Triangle |
三角形 |
Drawing_ManyLineSegements |
多线段 |
Drawing_Curve |
曲线 |
今天只讲述 矩形:Drawing_Rectangular
1:记录图形第一个绘制点
只有鼠标点击后才能获取当前点击点的位置,所以,记录按下点操作应该是在鼠标的mousePressEvent中实现的。
void QCustomQGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * e)
{
//TODO:鼠标左键,点击绘制图形;鼠标右键,点击拖动图形
QGraphicsScene::mousePressEvent(e);
if (e->button() & Qt::LeftButton)
{
//当图形处于绘制状态时
if (m_enumShape!= Drawing_Normal)
{
//记录鼠标按下的点
m_vetPoints.push_back(e->scenePos());
}
}
}
代码解析:当进入到鼠标按下消息后,只有在左键按下状态时,才做绘图操作,并且当前形状枚举类型有效。
2:实时获取鼠标最新位置并绘图
鼠标想要实时绘制,那一定是在鼠标的mouseMoveEvent事件中操作的。
void QCustomQGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e)
{
//TODO:鼠标移动时,如果存在有效图形类型,进行图形绘制
QGraphicsScene::mouseMoveEvent(e);
if (m_enumShape!= Drawing_Normal)
{
m_pTempLayer->DrawShape(m_enumShape, m_vetPt, e->scenePos());
}
}
代码解析:当鼠标进入到mouseMoveEvent事件后,并且,当前枚举类型处于有效状态时,需要实时绘制图形。
函数DrawShape的讲解:
参数1:图形的枚举类型,根据不同枚举,绘制不同的图形
参数2:vector<QPointF>传入已经记录的鼠标点,可以是多个,但最少是1个。就例如当前绘制矩形来说,该容器中只是存储了一个绘制点。
参数3:鼠标在mouseMoveEvent中实时拖动点
DrawShape函数实现代码,如下:
void QTempCanvasLayer::DrawShape(ENUM_DrawingGraphic enumShape, std::vector<QPointF> vetPt, QPointF ptCurrent)
{
m_pTempCanvasImg->fill(Qt::transparent);
m_pTempPainter->setRenderHint(QPainter::Antialiasing, true);
m_pTempPainter->setCompositionMode(QPainter::CompositionMode_Source);
m_pTempPainter->setPen(QPen(QColor(51, 51, 51), 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
switch (enumShape)
{
case Drawing_Circular: //圆形
break;
case Drawing_StraightLine: //直线
break;
case Drawing_Rectangular: //矩形
m_pTempPainter->drawRect(QRectF(vetPt[0], ptCurrent));
break;
case Drawing_Triangle: //三角形
break;
case Drawing_ManyLineSegements: //多线段
break;
case Drawing_Curve: //曲线
break;
default:
break;
}
update();
}
代码讲解:switch语句之前的内容都是在设置图形的风格,比如:setRenderHint防止图形走样;最需要我们注意的是下面一句代码:
m_pTempCanvasImg->fill(Qt::transparent);
如果你忘记设置了,当鼠标在拖动绘制图形时,会导致拖拽线条重叠的效果,就如下面展示效果一样,如图所示:
3:释放绘制点,绘制最终图形
鼠标事件:mouseReleaseEvent
void QCustomQGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * e)
{
//TODO:鼠标释放之后操作
QGraphicsScene::mouseReleaseEvent(e);
if (m_enumShape == Drawing_Normal)
{
return;
}
//存在有效的图形类型,进行最终图形绘制
if (e->button() & Qt::RightButton)
{
if (m_enumShape == Drawing_Rectangular)
{
//绘制直线,需要存储两个有效点
if (m_vetPt.size() == 2)
{
this->DrawRealShape(m_vetPt);
//如果当前正在绘制图形,直接清除
this->ClearCurrentDrawingShape();
}
}
}
}
代码解析:触发了鼠标释放事件后,并且是鼠标右键点击(在这里都是以鼠标右键点击作为最终的图形绘制完成),此时,根据不同的枚举类型进行图形绘制。
对于矩形图形来说,只需要两个有效的点就会完整对图形的绘制,其中this->DrawRealShape中进行最终点的绘制。
一个图形数据绘制成功之后,需要将上一次存储的临时点进行清除,以备后续图形绘制使用,说白了,也就是vector<QPointF>容器需要清除
实现完成了鼠标的三大事件,一个完整的实时鼠标图形绘制思路已经完成了。文章来源:https://www.toymoban.com/news/detail-553986.html
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓文章来源地址https://www.toymoban.com/news/detail-553986.html
到了这里,关于Qt如何实现实时鼠标绘制图形的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!