《QT从基础到进阶·十五》用鼠标绘制矩形(QGraphicsView、QPainter、QGraphicsRectItem)

以下是鼠标绘制矩形最全的一种用法,完整源码将会放在最后面。

QT版本:5.15.2

VS版本:2019

1、在界面加载一张图片

界面的搭建选用QGraphicsView,自定义类GraphicsView继承QGraphicsView,在主程序中点击按钮打开 图片,相关代码如下:

cpp 复制代码
void testString::on_button_clicked()
{

    QString fileName = QFileDialog::getOpenFileName(this, "open", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), "image (*.bmp *.png *.jpg)");
    if (fileName.isEmpty())
    {
        return;
    }
    QImage image(fileName);
    gview->setBackImage(image);
}

2、创建矩形绘制对象,并绘制、移动矩形

在GraphicsView类中创建矩形绘制对象,并初始化该对象用于绘制矩形。在GraphicsView类的鼠标事件中设置绘制矩形时鼠标按下,移动,释放操作。

cpp 复制代码
DrawROI* m_drawROI;
m_drawROI = new DrawROI(this);
m_drawROI->isDrawMultipleROIs(false);  //是否允许画多个矩形

void GraphicsView::mousePressEvent(QMouseEvent* event)
{
	QPoint nViewPoint = event->pos();
	m_drawROI->changeROIBegin(nViewPoint);
	QGraphicsView::mousePressEvent(event);
}

void GraphicsView::mouseMoveEvent(QMouseEvent* event)
{
    //鼠标按住左键移动
    if (event->buttons() & Qt::LeftButton) {
        //绘制矩形时鼠标移动处理
        m_drawROI->changeROIInProgress(event->pos());
    }
    //设置鼠标形状
    m_drawROI->changeMouseShape(event->pos());
    
    QGraphicsView::mouseMoveEvent(event);
}

void GraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton) {
        //矩形绘制结束
        m_drawROI->changeROIEnd(event->pos());
    }

    QGraphicsView::mouseReleaseEvent(event);

}

3、对绘制的矩形长宽进行修改和界面缩放

矩形长宽的拖动会在DrawROI类中实现,界面的缩放把DrawROI类中的功能放入GraphicsView中的滚轮事件中

cpp 复制代码
void GraphicsView::wheelEvent(QWheelEvent* ev)
{
    //放大图元
    m_graphicsViewTool->ScaleImage(ev);
    //图元放大,在图元上画的矩形不会放大,下面方法是让画的矩形和图元同比例放大,这里的画框是用QPainter方式,画出的东西不会随QGraphicsItem图元改变而改变
    //如果在图元上依然用QGraphicsItem图元来画框,那他们会一起改变,自动同比例放大缩小,因为都是属于QGraphics系列
    m_drawROI->ScaleROIS(ev, m_graphicsViewTool->GetScale());
}

4、绘制多个矩形并进行删除保存

绘制多个矩形需要做如下设置:

cpp 复制代码
m_drawROI->isDrawMultipleROIs(true);  //是否允许画多个矩形

对矩形进行右键删除和保存需要用到GraphicsView的右键菜单事件

cpp 复制代码
 m_pOptMenu = new QMenu(this);
 m_pDelAction = new QAction(QStringLiteral("删除"), this);
 connect(m_pDelAction, &QAction::triggered, m_drawROI, &DrawROI::DeleteCurrentROI);
 m_pSaveAction = new QAction(QStringLiteral("保存"), this);
 connect(m_pSaveAction, &QAction::triggered, m_drawROI, &DrawROI::saveAllROIImage);

    m_pOptMenu->addAction(m_pDelAction);
    m_pOptMenu->addAction(m_pSaveAction);

void GraphicsView::contextMenuEvent(QContextMenuEvent* ev)
{
    QPoint mousePos = ev->pos();

    //QRect.contains被给的点在矩形内部返回true
    //场景坐标
    QPointF fScenePoint = this->mapToScene(mousePos);
    //图形项坐标
    QGraphicsItem* pItem = this->scene()->itemAt(fScenePoint, QTransform());

    if (NULL != pItem)
    {
        QPointF fItemPoint = pItem->mapFromScene(fScenePoint);   //获取图形项坐标
        QPoint itemPoint(fItemPoint.x(), fItemPoint.y());

        for (int i = 0; i < m_drawROI->getRoiRect().size(); i++)
        {
            if (m_drawROI->getRoiRect()[i].contains(itemPoint))
            {
                m_pOptMenu->exec(QCursor::pos());
                break;
            }
        }
    }
    ev->accept();
}

=====================

完整源码下载

📢博客主页: 主页

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📢本文由 梦回阑珊 原创,首发于 CSDN,转载注明出处🙉

📢代码改变世界,你来改变代码!✨

相关推荐
我只会发热7 分钟前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
懷淰メ16 分钟前
PyQt飞机大战游戏(附下载地址)
开发语言·python·qt·游戏·pyqt·游戏开发·pyqt5
hummhumm30 分钟前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
宁静@星空36 分钟前
006-自定义枚举注解
java·开发语言
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
武子康1 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
珹洺1 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
每天吃饭的羊1 小时前
python里的数据结构
开发语言·python
码农飞飞1 小时前
详解Rust枚举类型(enum)的用法
开发语言·rust·match·枚举·匹配·内存安全
孙同学要努力1 小时前
C++知识整理day1——前置基础知识整理(命名空间、输入输出、函数重载、引用)
开发语言·c++