文章目录
-
-
- 一、QGraphicsView相关整理
- 二、QGraphicsView架构下实时鼠标绘制图形
-
- [2.1 鼠标拖拽绘图说明](#2.1 鼠标拖拽绘图说明)
- [2.2 记录图形第一个绘制点](#2.2 记录图形第一个绘制点)
- [2.3 实时获取鼠标最新位置并绘图](#2.3 实时获取鼠标最新位置并绘图)
- [2.4 释放绘制点,绘制最终图形](#2.4 释放绘制点,绘制最终图形)
- [三、QGraphicsView 在鼠标点击处进行放大缩小](#三、QGraphicsView 在鼠标点击处进行放大缩小)
-
一、QGraphicsView相关整理
项目中频繁地使用了QGraphicsView相关的类
(1)继承QGraphicsView,改写下面的protected成员函数进行自定义操作:
cpp
protected:
void keyPressEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
void paintEvent(QPaintEvent * event);
void mouseMoveEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
使用中注意,如果想使QGraphicsView中已定义的操作任然有效,则需要在函数定义代码中添加下列语句, 以便实现父类已经是实现的默认操作。
cpp
QGraphicsView::keyPressEvent(event);
QGraphicsView::mousePressEvent(event);
QGraphicsView::mouseMoveEvent(event);
QGraphicsView::paintEvent(event);
QGraphicsView::mouseDoubleClickEvent(event);
QGraphicsView::wheelEvent(event);
(2) 可创建QGraphicsScene对象添加到QGraphicsView对象中(setScene(QgraphicsScene* scene)),可以使用同样的方法继承QGraphicsScene进行自定义操作;
(3) QGraphicsView中有**horizontalScrollBar()和verticalScrollBar()**可以返回视图中的滚动条,下面的代码可以设置滚动条的显示模式
cpp
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// 设置在视图中进行拖动
setDragMode(QGraphicsView::ScrollHandDrag);
(4)当使用自定义的右键选择菜单时,需要下面的语句,在槽函数on_graphicsView_customContextMenuRequested(QPoint) 中定义相关操作
cpp
m_graphicsView->setContextMenuPolicy (Qt::CustomContextMenu);
connect(m_graphicsView,SIGNAL(customContextMenuRequested(QPoint)),this, SLOT(on_graphicsView_customContextMenuRequested(QPoint)));
(5)QGraphicsItem相关:
QGraphicsTextItem, QGraphicsLineItem, QGraphicsRectItem 三个Graphicsitem
cpp
QGraphicsTextItem *title = new QGraphicsTextItem();
title->setPlainText(name);
title->setPos(10, 10);
title->setFont(QFont(QString::fromLocal8Bit ("楷体"),15));
title->setDefaultTextColor(QColor(160, 160, 160));
title->setZValue(30);//设置图层
QGraphicsLineItem *linetemp = new QGraphicsLineItem();
QPen pen = linetemp->pen();
pen.setColor(QColor(81, 82, 84));
pen.setWidth(4);
linetemp->setPen(pen);
linetemp->setLine(QLineF(0, 0, 10, 10));
linetemp->setZValue (12);
QGraphicsRectItem* m_overAreaTop = new QGraphicsRectItem();
m_overAreaTop->setRect(0,0,10,10);
m_overAreaTop->setBrush(QBrush(QColor(64, 66, 68)));//填充色
m_overAreaTop->setPen(QPen(QColor(64, 66, 68)));//边框线
m_overAreaTop->setZValue(10);
每个item设置ZValue可以在对象重合时选择显示哪个对象显示在最前面。
可以通过boundingRect()获取item的边界框QRect类对象,并可以通过mapFromGlobal、mapRectToParent、mapRectToScene等进行坐标转换,最后通过QRect的contains()判断相关点的包含问题。
二、QGraphicsView架构下实时鼠标绘制图形
2.1 鼠标拖拽绘图说明
想要实现鼠标拖拽绘图的效果,离不开鼠标的三大事件:按下 、移动 、释放
绘制矩形框的核心流程
第一步:鼠标左键点击,记录初始点击位置
第二步:在窗口中移动鼠标,实时获取鼠标拖动点,根据拖动点绘制指定形状
第三步:鼠标点击右键释放鼠标,绘制最终图形
在进行鼠标点击绘制的时候,为了兼容多个图形的实时绘制,这里,不只是用两个QPoint成员变量记录鼠标点,而是采取了vector<QPontF>容器存储的方式。
例如:三角形图形,需要三个点才能确定图形;曲线图形,是由N多个点才能确定图形;等等...
|--------|---------------------------|-------|
| 图形枚举类型 | 枚举类型 | 形状 |
| 图形枚举类型 | Drawing_Normal | 无图形绘制 |
| 图形枚举类型 | Drawing_Circular | 圆形 |
| 图形枚举类型 | Drawing_StraightLine | 直线 |
| 图形枚举类型 | Drawing_Rectangular | 矩形 |
| 图形枚举类型 | Drawing_Triangle | 三角形 |
| 图形枚举类型 | Drawing_ManyLineSegements | 多线段 |
| 图形枚举类型 | Drawing_Curve | 曲线 |
2.2 记录图形第一个绘制点
这里以Drawing_Rectangular为例
鼠标点击后才能获取当前点击点的位置,记录按下点操作应该是在鼠标的mousePressEvent中实现的
cpp
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.3 实时获取鼠标最新位置并绘图
鼠标想要实时绘制,在移动鼠标的mouseMoveEvent事件中操作的。
cpp
void QCustomQGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e)
{
//TODO:鼠标移动时,如果存在有效图形类型,进行图形绘制
QGraphicsScene::mouseMoveEvent(e);
if (m_enumShape!= Drawing_Normal)
{
m_pTempLayer->DrawShape(m_enumShape, m_vetPt, e->scenePos());
}
}
DrawShape函数 的讲解
- 参数1:图形的枚举类型,根据不同枚举,绘制不同的图形
- 参数2:
vector<QPointF>
传入已经记录的鼠标点,可以是多个,但最少是1个。就例如当前绘制矩形来说,该容器中只是存储了一个绘制点。 - 参数3:鼠标在mouseMoveEvent中实时拖动点
DrawShape函数实现代码,如下:
cpp
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();
}
2.4 释放绘制点,绘制最终图形
鼠标事件:mouseReleaseEvent 绘制鼠标
cpp
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(); //如果当前正在绘制图形,直接清除
}
}
}
}
三、QGraphicsView 在鼠标点击处进行放大缩小
使用QGraphicsView类的设置属性函数.在构造函数中增加下面两个函数即可。
cpp
ui->View_ImageOpro->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ui->View_ImageOpro->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
setDragMode枚举值:
- QGraphicsView::NoDrag,
- QGraphicsView::RubberBandDrag
- QGraphicsView::ScrollHandDrag
cpp
MyGraphicsView::MyGraphicsView()
{
//设置ui控件属性
setDragMode(QGraphicsView::NoDrag);
scale_m = 1; //图形原始比例
setStyleSheet("padding: 0px; border: 0px;");//无边框
setMouseTracking(true); //跟踪鼠标位置
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //隐藏水平条
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //隐藏竖条
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}
void MyGraphicsView::wheelEvent ( QWheelEvent * event )
{
if (event->modifiers() == Qt::CTRL){ //按住ctrl键 可以放大缩小
if((event->delta() > 0)&&(scale_m >= 50)) return; //最大放大到原始图像的50倍
// 图像缩小到自适应大小之后就不继续缩小; 重置图片大小和位置,使之自适应控件窗口大小
else if((event->delta() < 0)&&(scale_m <= 0.01)) return;
else
{
// 当前放缩倍数;
qreal scaleFactor = this->matrix().m11();
scale_m = scaleFactor;
int wheelDeltaValue = event->delta();
if (wheelDeltaValue > 0) this->scale(1.2, 1.2); // 向上滚动,放大;
else this->scale(1.0 / 1.2, 1.0 / 1.2); // 向下滚动,缩小;
update();
}
}
}
QPainter鼠标绘制矩形,多边形:https://blog.csdn.net/Stone_OverLooking/article/details/112886734