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

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

方法一实现代码:
.h

#ifndef MAPSELECTITEM_H
#define MAPSELECTITEM_H

#include 
#include 
#include 

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 
#include 
#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 
#include 

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 
#include 
#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();
}

你可能感兴趣的:(QT,c++,qt,开发语言)