方法一:继承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();
}