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

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

相关推荐
6Hzlia几秒前
【Hot 100 刷题计划】 LeetCode 102. 二叉树的层序遍历 | C++ 极简 DFS 巧解
c++·leetcode·深度优先
zzb15806 分钟前
「Kotlin 泛型深度图解:从入门到实战 + 委托框架揭秘」
开发语言·windows·kotlin
石油人单挑所有15 分钟前
基于多设计模式下的同步&异步日志系统测试报告
服务器·c++·vscode·设计模式
.千余18 分钟前
【Linux】开发工具1
linux·运维·服务器·c语言·学习
人道领域21 分钟前
【LeetCode刷题日记】225.用队列实现栈--三招实现栈操作(多种思维)
java·开发语言·算法·leetcode·面试
Mr_pyx23 分钟前
【告别for循环】Java Stream 流式编程精通:从入门到源码级的性能优化
java·开发语言·性能优化
:12123 分钟前
java基础--数组
java·开发语言
爱上好庆祝25 分钟前
学习js第一天(出发新世界)
开发语言·前端·javascript·css·学习·html·ecmascript
小短腿的代码世界28 分钟前
Qwt性能优化与源码级深度解析:工业级图表控件的极限性能调优
开发语言·qt·信息可视化·性能优化
lsx20240642 分钟前
jQuery UI 实例
开发语言