《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,转载注明出处🙉

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

相关推荐
浩子智控6 小时前
python程序打包的文件地址处理
开发语言·python·pyqt
casual~6 小时前
第?个质数(埃氏筛算法)
数据结构·c++·算法
Jackey_Song_Odd6 小时前
Part 1:Python语言核心 - 序列与容器
开发语言·windows·python
Elnaij6 小时前
从C++开始的编程生活(20)——AVL树
开发语言·c++
似水明俊德6 小时前
12-C#
开发语言·数据库·oracle·c#
hanbr6 小时前
【C++ STL核心】vector:最常用的动态数组容器(第九天核心)
开发语言·c++
仰泳的熊猫6 小时前
题目2308:蓝桥杯2019年第十届省赛真题-旋转
数据结构·c++·算法·蓝桥杯
菜鸟‍7 小时前
【后端项目】苍穹外卖day01-开发环境搭建
java·开发语言·spring boot
lzksword7 小时前
C++ Builder XE OpenDialog1打开多文件并显示xls与xlsx二种格式文件
java·前端·c++
青槿吖7 小时前
【保姆级教程】Spring事务控制通关指南:XML+注解双版本,避坑指南全奉上
xml·java·开发语言·数据库·sql·spring·mybatis