Qt(十二)Graphics View 绘图架构(三)

文章目录

      • 一、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

相关推荐
明月看潮生15 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录25 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
逊嘘42 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
Half-up1 小时前
C语言心型代码解析
c语言·开发语言
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng1 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word
小白学大数据1 小时前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin