两种QGraphicsItem方式实现橡皮擦功能(矩形选中框)

news2024/12/23 15:26:17

请添加图片描述

方法一:继承QGraphicsItem实现橡皮擦功能。(gif中红色矩形框)
方法二:继承QGraphicsRectItem实现的橡皮擦功能。(gif中蓝色矩形框)
通过以上GIF可以看出两款橡皮擦都具有位置拖动和大小拖动的功能,但是方法一的红色矩形框在一些特殊情况下的位置时,会出现无效的问题,但是方法二不存在这个问题。

方法一实现代码:
.h

#ifndef MAPSELECTITEM_H
#define MAPSELECTITEM_H

#include <QGraphicsItem>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>

class MapSelectItem : public QGraphicsItem
{
public:
    MapSelectItem(QPointF p);
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
private:
    QRectF m_leftTopRect;
    QRectF m_leftBottomRect;
    QRectF m_rightTopRect;
    QRectF m_rightBottomRect;
    QRectF m_baseRectF;
    bool m_mousePressed = false;
    bool m_lfTopSelectFg = false;
    bool m_lfBottomSelectFg = false;
    bool m_rtTopSelectFg = false;
    bool m_rtBottomSelectFg = false;
    int m_selectAreaSize = 0;
    QPointF m_lastPointF;
    double m_scaleFactor = 0.0;
    int m_w = 0;
    int m_h = 0;
};

#endif // MAPSELECTITEM_H

.cpp

#include "mapselectitem.h"
#include <QDebug>
#include <QGraphicsScene>
#define SelectAreaSize 30

MapSelectItem::MapSelectItem(QPointF p)
{
    this->setFlag(QGraphicsItem::ItemIsMovable, true);
//    this->setAcceptHoverEvents(true);

    m_baseRectF = QRectF(p.x(),p.y(),100,100);
    m_w = 100;
    m_h = 100;
}

QRectF MapSelectItem::boundingRect() const
{
    return m_baseRectF;
}

void MapSelectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);

    m_scaleFactor = painter->matrix().m11();
    m_selectAreaSize = SelectAreaSize/m_scaleFactor;
    QPen pen = painter->pen();
    pen.setWidthF(pen.widthF() * 2 / m_scaleFactor);  //等比例设置线宽,当前设置为2倍线宽

    m_baseRectF.setWidth(m_w/m_scaleFactor);
    m_baseRectF.setHeight(m_h/m_scaleFactor);

    //背景框
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(QColor("#20ff0000")));
    painter->drawRect(m_leftTopRect.center().x(),m_rightTopRect.center().y(),m_rightBottomRect.center().x() - m_leftTopRect.center().x(),
                      m_rightBottomRect.center().y() - m_leftTopRect.center().y());

    pen.setColor(QColor("#ff0000"));
    painter->setPen(pen);
    painter->setBrush(QBrush(QColor("#ff0000")));

    m_leftTopRect = QRectF(m_baseRectF.left(),m_baseRectF.top(),m_selectAreaSize,m_selectAreaSize);
    m_leftBottomRect = QRectF(m_baseRectF.left(),m_baseRectF.bottom() - m_selectAreaSize,m_selectAreaSize,m_selectAreaSize);
    m_rightTopRect = QRectF(m_baseRectF.right() - m_selectAreaSize,m_baseRectF.top(),m_selectAreaSize,m_selectAreaSize);
    m_rightBottomRect = QRectF(m_baseRectF.right() - m_selectAreaSize,m_baseRectF.bottom() - m_selectAreaSize,m_selectAreaSize,m_selectAreaSize);
    painter->drawEllipse(m_leftTopRect);
    painter->drawEllipse(m_leftBottomRect);
    painter->drawEllipse(m_rightTopRect);
    painter->drawEllipse(m_rightBottomRect);

    pen.setStyle(Qt::DashLine);
    painter->setPen(pen);
    painter->drawLine(m_leftTopRect.center(),m_leftBottomRect.center());
    painter->drawLine(m_leftTopRect.center(),m_rightTopRect.center());
    painter->drawLine(m_rightTopRect.center(),m_rightBottomRect.center());
    painter->drawLine(m_leftBottomRect.center(),m_rightBottomRect.center());

}

void MapSelectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mousePressEvent(event);
    if (m_leftTopRect.contains(event->scenePos()))
        m_lfTopSelectFg = true;
    else if (m_leftBottomRect.contains(event->scenePos()))
        m_lfBottomSelectFg = true;
    else if (m_rightTopRect.contains(event->scenePos()))
        m_rtTopSelectFg = true;
    else if (m_rightBottomRect.contains(event->scenePos()))
        m_rtBottomSelectFg = true;
    else
        m_mousePressed = true;
    m_lastPointF = event->scenePos();
}

void MapSelectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseReleaseEvent(event);
    m_mousePressed = false;
    m_lfTopSelectFg = false;
    m_lfBottomSelectFg = false;
    m_rtTopSelectFg = false;
    m_rtBottomSelectFg = false;
}

/*add in 220622 */
void MapSelectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF pos = event->scenePos();
    if (m_mousePressed) {
        m_baseRectF = QRectF(m_baseRectF.x() + pos.x() - m_lastPointF.x(),m_baseRectF.y() + pos.y() - m_lastPointF.y()
                             ,m_baseRectF.width(),m_baseRectF.height());
    }
    else if (m_lfTopSelectFg)
    {
        double x = m_baseRectF.x();
        double y = m_baseRectF.y();
        m_baseRectF.setX(x + pos.x() - x);
        m_baseRectF.setY(y + pos.y() - y);
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setX(x);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setY(y);
    }
    else if (m_lfBottomSelectFg)
    {
        double x = m_baseRectF.x();
        double h = m_baseRectF.height();
        m_baseRectF.setX(m_baseRectF.x() + pos.x() - m_lastPointF.x());
        m_baseRectF.setHeight(m_baseRectF.height() + pos.y() - m_lastPointF.y());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setX(x);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setHeight(h);
    }
    else if (m_rtTopSelectFg)
    {
        double y = m_baseRectF.y();
        double w = m_baseRectF.width();
        m_baseRectF.setY(m_baseRectF.y() + pos.y() - m_lastPointF.y());
        m_baseRectF.setWidth(m_baseRectF.width() + pos.x() - m_lastPointF.x());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setWidth(w);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setY(y);
    }
    else if (m_rtBottomSelectFg)
    {
        double w = m_baseRectF.width();
        double h = m_baseRectF.height();
        m_baseRectF.setWidth(m_baseRectF.width() + pos.x() - m_lastPointF.x());
        m_baseRectF.setHeight(m_baseRectF.height() + pos.y() - m_lastPointF.y());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setWidth(w);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setHeight(h);
    }
    m_w = m_baseRectF.width()*m_scaleFactor;
    m_h = m_baseRectF.height()*m_scaleFactor;
    m_lastPointF = event->scenePos();
    this->scene()->update();
}

方法二实现代码:
.h

#ifndef MAPSELECTAREA_H
#define MAPSELECTAREA_H

#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>

class MapSelectArea : public QGraphicsRectItem
{
public:
    MapSelectArea(QGraphicsScene *scene, QObject *parent);

public:
    void setPos(QPointF p);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
private:
    double m_w;
    double m_h;
    QRectF m_baseRectF;
    QRectF m_leftTopRect;
    QRectF m_leftBottomRect;
    QRectF m_rightTopRect;
    QRectF m_rightBottomRect;
    int m_selectAreaSize = 0;
    double m_scaleFactor = 0.0;

    bool m_mousePressed = false;
    bool m_lfTopSelectFg = false;
    bool m_lfBottomSelectFg = false;
    bool m_rtTopSelectFg = false;
    bool m_rtBottomSelectFg = false;
    QPointF m_lastPointF;
};

#endif // MAPSELECTAREA_H

.cpp

#include "mapselectarea.h"
#include <QGraphicsScene>
#include "graphicsmap.h"
#include <QDebug>
#define SelectAreaSize 30


MapSelectArea::MapSelectArea(QGraphicsScene *scene, QObject *parent)
{
    scene->addItem(this);
    this->setFlag(QGraphicsItem::ItemIsMovable, true);
    this->setAcceptHoverEvents(true);
    this->setBrush(Qt::red);

}

void MapSelectArea::setPos(QPointF p)
{
    this->setRect(p.x(),p.y(),100,100);
    m_w = 100;
    m_h = 100;
}

void MapSelectArea::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);

    QPen pen;
    m_scaleFactor = painter->matrix().m11();
    m_selectAreaSize = SelectAreaSize/m_scaleFactor;
    m_baseRectF = rect();
    this->setRect(m_baseRectF.x(),m_baseRectF.y(),m_w/m_scaleFactor,m_h/m_scaleFactor);
    pen.setWidthF(pen.widthF() * 2 / m_scaleFactor);  //等比例设置线宽,当前设置为2倍线宽


    //背景框
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(QColor("#2048CBD4")));
    painter->drawRect(m_leftTopRect.center().x(),m_rightTopRect.center().y(),m_rightBottomRect.center().x() - m_leftTopRect.center().x(),
                      m_rightBottomRect.center().y() - m_leftTopRect.center().y());

    pen.setColor(QColor("#48CBD4"));
    painter->setPen(pen);
    painter->setBrush(QBrush(QColor("#48CBD4")));

    m_leftTopRect = QRectF(m_baseRectF.left(),m_baseRectF.top(),m_selectAreaSize,m_selectAreaSize);
    m_leftBottomRect = QRectF(m_baseRectF.left(),m_baseRectF.bottom() - m_selectAreaSize,m_selectAreaSize,m_selectAreaSize);
    m_rightTopRect = QRectF(m_baseRectF.right() - m_selectAreaSize,m_baseRectF.top(),m_selectAreaSize,m_selectAreaSize);
    m_rightBottomRect = QRectF(m_baseRectF.right() - m_selectAreaSize,m_baseRectF.bottom() - m_selectAreaSize,m_selectAreaSize,m_selectAreaSize);
    painter->drawEllipse(m_leftTopRect);
    painter->drawEllipse(m_leftBottomRect);
    painter->drawEllipse(m_rightTopRect);
    painter->drawEllipse(m_rightBottomRect);

    pen.setStyle(Qt::DashLine);
    painter->setPen(pen);
    painter->drawLine(m_leftTopRect.center(),m_leftBottomRect.center());
    painter->drawLine(m_leftTopRect.center(),m_rightTopRect.center());
    painter->drawLine(m_rightTopRect.center(),m_rightBottomRect.center());
    painter->drawLine(m_leftBottomRect.center(),m_rightBottomRect.center());
}

void MapSelectArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mousePressEvent(event);
    if (m_leftTopRect.contains(event->scenePos()))
        m_lfTopSelectFg = true;
    else if (m_leftBottomRect.contains(event->scenePos()))
        m_lfBottomSelectFg = true;
    else if (m_rightTopRect.contains(event->scenePos()))
        m_rtTopSelectFg = true;
    else if (m_rightBottomRect.contains(event->scenePos()))
        m_rtBottomSelectFg = true;
    else
        m_mousePressed = true;
    m_lastPointF = event->scenePos();
}

void MapSelectArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseReleaseEvent(event);
    m_mousePressed = false;
    m_lfTopSelectFg = false;
    m_lfBottomSelectFg = false;
    m_rtTopSelectFg = false;
    m_rtBottomSelectFg = false;
}

/*add in 220622 */
void MapSelectArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF pos = event->scenePos();
    if (m_mousePressed) {
        m_baseRectF = QRectF(m_baseRectF.x() + pos.x() - m_lastPointF.x(),m_baseRectF.y() + pos.y() - m_lastPointF.y()
                             ,m_baseRectF.width(),m_baseRectF.height());
    }
    else if (m_lfTopSelectFg)
    {
        double x = m_baseRectF.x();
        double y = m_baseRectF.y();
        m_baseRectF.setX(x + pos.x() - x);
        m_baseRectF.setY(y + pos.y() - y);
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setX(x);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setY(y);
    }
    else if (m_lfBottomSelectFg)
    {
        double x = m_baseRectF.x();
        double h = m_baseRectF.height();
        m_baseRectF.setX(m_baseRectF.x() + pos.x() - m_lastPointF.x());
        m_baseRectF.setHeight(m_baseRectF.height() + pos.y() - m_lastPointF.y());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setX(x);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setHeight(h);
    }
    else if (m_rtTopSelectFg)
    {
        double y = m_baseRectF.y();
        double w = m_baseRectF.width();
        m_baseRectF.setY(m_baseRectF.y() + pos.y() - m_lastPointF.y());
        m_baseRectF.setWidth(m_baseRectF.width() + pos.x() - m_lastPointF.x());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setWidth(w);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setY(y);
    }
    else if (m_rtBottomSelectFg)
    {
        double w = m_baseRectF.width();
        double h = m_baseRectF.height();
        m_baseRectF.setWidth(m_baseRectF.width() + pos.x() - m_lastPointF.x());
        m_baseRectF.setHeight(m_baseRectF.height() + pos.y() - m_lastPointF.y());
        if (m_baseRectF.width() <= m_selectAreaSize*2)
            m_baseRectF.setWidth(w);
        if (m_baseRectF.height() <= m_selectAreaSize*2)
            m_baseRectF.setHeight(h);
    }
    m_w = m_baseRectF.width()*m_scaleFactor;
    m_h = m_baseRectF.height()*m_scaleFactor;
    this->setRect(m_baseRectF.x(),m_baseRectF.y(),m_w/m_scaleFactor,m_h/m_scaleFactor);
    m_lastPointF = event->scenePos();
    this->scene()->update();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/527092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nacos必知必会:这些知识点你一定要掌握!

前言 Nacos 是一个开源的服务发现、配置管理和服务治理平台&#xff0c;是阿里巴巴开源的一款产品。 Nacos 可以帮助开发者更好地管理微服务架构中的服务注册、配置和发现等问题&#xff0c;提高系统的可靠性和可维护性。 本文将介绍 Nacos 的必知必会知识点&#xff0c;包括…

Zookeeper基础和简单使用

安装与配置 概念 基于观察者模式设计的分布式服务管理框架&#xff0c;负责存储和管理大家都关心数据&#xff0c;然后接受观察者的注册&#xff0c;一单这些数据的这状态发生了变化&#xff0c;Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应 特点…

当JS遇到加密:解密你的JS代码!

作为一名程序员&#xff0c;我们经常会遇到各种加密算法&#xff0c;比如常见的AES、RSA、MD5等等&#xff0c;但是今天我想和大家聊一聊一个日常生活中比较常见的加密方式——JavaScript加密。 在我们日常浏览网页时&#xff0c;经常会看到一些网站的JavaScript代码经过加密&…

【Redis】布隆过滤器原理与应用

文章目录 原理应用实战总结 布隆过滤器&#xff08;Bloom Filter&#xff09;是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。 它的优点是空间效率和查询时间都比一般的算法要好的多&#xff…

AJAX实现搜索联想 自动补全

分析: 1.想实现联想搜索需要数据库的数据支撑,需要进行模糊查询,搜索出所有包含用户输入的关键字信息,并将这些信息都反馈到前端,简化用户输入,从而提高用户的体验。 2.为了提高用户的使用体验&#xff0c;整个页面不能全部刷新&#xff0c;需要局部刷新&#xff0c;为此需要…

Python中的各种报错-一般错误

目录 ValueError: check_hostname requires server_hostname missing 1 required positional argument: self xxx is not a package libpng warning: iCCP: cHRM chunk does not match sRGB check_hostname requires server_hostname python 安装第三方库&#xff0c;超时…

MQTTC数据桥接上云

[小 迪 导 读]&#xff1a;在工业物联网蓬勃发展的背景下&#xff0c;私有化部署已经不能满足当前的发展趋势了&#xff0c;因此dgiot在原有基础上进行创新&#xff0c;将私有化部署的区域数控一体机上的数据通过mqtt桥接的方式上传到云服务器上&#xff0c;完成数据的实时同步…

Baumer工业相机堡盟工业相机软件CameraExplorer常见功能使用说明一

Baumer工业相机堡盟工业相机软件CameraExplorer常见功能使用说明一 Baumer工业相机Baumer工业相机图像采集功能Baumer工业相机图像基本参数设置 Baumer工业相机 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、…

【前端提效】-- Chrome浏览器开发者工具使用技巧

介绍一下 DevTools 的一些好用的技巧&#xff0c;它能够很好地帮助你提高生产力和解决问题的能力。 1、打开命令行 或者使用&#xff1a;快捷键 Ctrl Shift P (Mac&#xff1a; ⌘ Shift P ) 命令行可以做很多事情&#xff0c;包括但不限于截图、更换主题等 2、控制 DevT…

暑假线上兼职:300-500元/小时,安利一个大学生也能月入8K的线上兼职

在后台经常收到这样的留言&#xff1a; 快接近暑假了&#xff0c;有没有线上兼职推荐&#xff1f; 如何提升自己的眼界和能力&#xff0c;为之后的职场铺路&#xff1f; 不知道有多少朋友是想提升自己获取资源信息的速度&#xff0c;发展自己的爱好&#xff0c;或者增加第二收入…

用友U8增加查询条件

1、检查要增加的条件是否在该表单中&#xff1b; 2、在查询条件中增加查询条件的管理方案 3、参照ID就是要参照的表 4、数据源&#xff0c;在要增加的表单数据库中查询该字段名&#xff0c;进行增加即可。 select * from purbillvouch where cpbvcode 0000000312 --PurBillV…

调用legend资源,生成地图图例

作者&#xff1a;lly 文章目录 前言一、接口详情二、具体实现三、结果展示 前言 最近很多小伙伴资源关于iServer图例的问题&#xff0c; 接下来我们就来介绍下如何使用iServer legend资源&#xff0c;生成地图图例 一、接口详情 请求示例 {"layerLegends": [{&quo…

达索的天线设计和仿真软件Antenna Magus 2023版本下载与安装配置教程

目录 前言一、Antenna Magus安装二、使用配置总结 前言 Antenna Magus软件是一款用于天线设计和仿真的软件&#xff0c;提供了一个全面的设计工具集&#xff0c;帮助工程师优化天线设计&#xff0c;同时减少设计周期。 Antenna Magus的主要特点&#xff1a; ——高级天线库&…

如何用 ChatGPT 帮你自动分析数据?

误判 好几天之前&#xff0c;我就在 ChatGPT 选单里看到了 Code Interpreter。它正在灰度测试中 —— 先给一部分用户试用&#xff0c;如果反响不错并做了一定改进&#xff0c;就能推广给更多用户。 可惜当时我没能正确理解它的含义&#xff0c;犯了一个大错误 —— 望文生义。…

ChatGPT 上线联网和插件功能;投资者看好新版搜索引擎

&#x1f680; ChatGPT 上线联网和插件功能 OpenAI宣布将在这周推出联网和插件功能&#xff0c;位于Alpha和Beta通道的ChatGPT Plus用户都可使用70多个上线的插件。 更新意味着ChatGPT将利用最新的信息和资讯为使用者提供服务。 上线的ChatGPT插件种类涵盖了行程安排助理、代…

Android开发-Android常用组件-Date Time组件

4.11 Date & Time组件 1.TextClock(文本时钟) TextClock是在Android 4.2(API 17)后推出的用来替代DigitalClock的一个控件&#xff01; TextClock可以以字符串格式显示当前的日期和时间&#xff0c;因此推荐在Android 4.2以后使用TextClock。 这个控件推荐在24进制的and…

[内网]RDP远程桌面密码凭证获取

文章目录 RDP保存凭据通过注册表查看当前主机本地连接过的目标机器记录查看当前主机保存的RDP凭据查看本地用户是否存有RDP密码文件通过密码文件获取guidMasterKey的值根据guidMasterKey找到对应Masterkey解密获取明文以上总结&#xff1a; 在授权渗透过程中&#xff0c;如果获…

PCB当中的跳线有什么作用

在PCB设计中&#xff0c;跳线是一种常见的连接方式。跳线是为了连接电路中的距离较远或无法直接连接的电路元件而设置的&#xff0c;其作用是非常重要的。在本文中&#xff0c;我们将探讨PCB中跳线的作用和应用。 一、什么是跳线 跳线是一种特殊的电路连接方式&#xff0c;它是…

EXCEL 0开头的数据处理

方法一&#xff1a;从数据库中存为csv 再新建一个EXCEL 数据——从文本/CSV 方法二&#xff1a; 在数据库里面加A&#xff0c;在EXCEL里面将A替换成 上单引号 ‘

【002】C++的关键字介绍

C的关键字介绍 引言一、关键字一览表二、数据类型相关的关键字三、存储相关的关键字四、控制语句相关的关键字总结 引言 &#x1f4a1; 作者简介&#xff1a;专注于C/C高性能程序设计和开发&#xff0c;理论与代码实践结合&#xff0c;让世界没有难学的技术。包括C/C、Linux、M…