GraphicsView实现添加背景、添加矩形、放缩、移动

该博文详细介绍了如何使用Qt库实现图形界面元素的交互,包括矩形元素的拖动、缩放和旋转功能。通过GraphicsRectItem、GraphicsScene、GraphicsView和SizeHandleRect等类的定义和实现,展示了鼠标事件处理、画布更新和图形变换等功能。同时,给出了一个主窗口的示例,用于创建和操作矩形,并提供了背景图片设置的接口。
摘要由CSDN通过智能技术生成

 graphicsrectitem.h

#ifndef GRAPHICSRECTITEM_H
#define GRAPHICSRECTITEM_H

#include <QGraphicsItem>
#include "sizehandlerect.h"

class GraphicsRectItem : public QGraphicsItem
{
public:
    GraphicsRectItem(const QRect & rect ,QGraphicsItem * parent);

    QRectF boundingRect() const;
    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
    void move(const QPointF & point);
    virtual Qt::CursorShape getCursor(SizeHandleRect::Direction dir );
    SizeHandleRect::Direction  hitTest( const QPointF & point ) const;
    virtual QRectF  rect() const;
    virtual void updateGeometry();
    QRectF m_rect;

private:

    typedef QVector<SizeHandleRect*> Handles;
    Handles m_handles;
    int selection_handle_size = 4;

protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    void setState(SelectionHandleState st);
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
};

#endif // GRAPHICSRECTITEM_H

graphicsscene.h

#ifndef GRAPHICSRECTITEM_H
#define GRAPHICSRECTITEM_H

#include <QGraphicsItem>
#include "sizehandlerect.h"

class GraphicsRectItem : public QGraphicsItem
{
public:
    GraphicsRectItem(const QRect & rect ,QGraphicsItem * parent);

    QRectF boundingRect() const;
    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
    void move(const QPointF & point);
    virtual Qt::CursorShape getCursor(SizeHandleRect::Direction dir );
    SizeHandleRect::Direction  hitTest( const QPointF & point ) const;
    virtual QRectF  rect() const;
    virtual void updateGeometry();
    QRectF m_rect;

private:

    typedef QVector<SizeHandleRect*> Handles;
    Handles m_handles;
    int selection_handle_size = 4;

protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    void setState(SelectionHandleState st);
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
};

#endif // GRAPHICSRECTITEM_H

graphicsview.h

#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H

#include <QGraphicsView>
#include <QKeyEvent>
#include <QWheelEvent>

class GraphicsView : public QGraphicsView
{
    Q_OBJECT

public:
    GraphicsView(QWidget *parent = 0);

protected:
    void keyPressEvent(QKeyEvent *event);
    void wheelEvent(QWheelEvent *event);
};

#endif // GRAPHICSVIEW_H

sizehandlerec.h

#ifndef SIZEHANDLERECT_H
#define SIZEHANDLERECT_H

#include <QGraphicsRectItem>

enum SelectionHandleState { SelectionHandleOff, SelectionHandleInactive, SelectionHandleActive };

class SizeHandleRect : public QGraphicsRectItem
{
public:
    enum Direction { LeftTop , Top, RightTop, Right, RightBottom, Bottom, LeftBottom, Left , Center, None};
    SizeHandleRect(QGraphicsItem* parent , QRectF rect, Direction dir);
    Direction dir() const;
    bool hitTest( const QPointF & point );
    void move(qreal x, qreal y );
    void setState(SelectionHandleState st);
protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
    const Direction m_dir;
    SelectionHandleState m_state;
};

#endif // SIZEHANDLERECT_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "GraphicsRect/graphicsscene.h"
#include "GraphicsRect/graphicsview.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_createRect_clicked();

    void on_pushButton_getRect_clicked();

    void on_pushButton_addPix_clicked();

private:
    Ui::MainWindow *ui;
    GraphicsScene *scene = NULL;
};

#endif // MAINWINDOW_H


下面是资源文件

graphicsrectitem.cpp

#include "graphicsrectitem.h"
#include <QPen>
#include <QPainter>
#include <QDebug>

GraphicsRectItem::GraphicsRectItem(const QRect &rect, QGraphicsItem *parent) :
    QGraphicsItem(parent)
{
    m_rect = rect;
    m_handles.reserve(SizeHandleRect::None);
    for (int i = SizeHandleRect::LeftTop; i <= SizeHandleRect::Left; ++i) {
        SizeHandleRect *shr = new SizeHandleRect(this, QRectF(0,0,1,1), static_cast<SizeHandleRect::Direction>(i));
        m_handles.push_back(shr);
    }
    updateGeometry();
    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    this->setAcceptHoverEvents(true);
}

void GraphicsRectItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
{
    QPointF local = mapFromScene(point);
    QString dirName;

    QRect delta =m_rect.toRect();
    switch (dir) {
    case SizeHandleRect::LeftTop:
        delta.setTopLeft(local.toPoint());

        break;
    case SizeHandleRect::Top:
        dirName = "Top";
        delta.setTop(local.y());
        break;

    case SizeHandleRect::RightTop:
        dirName = "RightTop";
        delta.setTopRight(local.toPoint());
        break;

    case SizeHandleRect::Left:
        dirName = "Left";
        delta.setLeft(local.x());
        break;
    case SizeHandleRect::Right:
        dirName = "Rigth";
        delta.setRight(local.x());
        break;

    case SizeHandleRect::LeftBottom:
        dirName = "LeftBottom";
        delta.setBottomLeft(local.toPoint());
        break;

    case SizeHandleRect::Bottom:
        dirName = "Bottom";
        delta.setBottom(local.y());
        break;

    case SizeHandleRect::RightBottom:
        dirName = "RightBottom";
        delta.setBottomRight(local.toPoint());
        break;

    default:
        break;
    }
    prepareGeometryChange();
//    if(m_isSquare)
//    {
//        delta.setHeight(delta.width());
//    }
    m_rect =delta;
    updateGeometry();
}

void GraphicsRectItem::move(const QPointF &point)
{
    QPointF local = mapFromScene(point);

    QRectF delta = QRectF(local, m_rect.size());

    prepareGeometryChange();
    m_rect =delta;
    updateGeometry();
}

Qt::CursorShape GraphicsRectItem::getCursor(SizeHandleRect::Direction dir)
{
    switch (dir) {
    case SizeHandleRect::Right:
        return Qt::SizeHorCursor;
    case SizeHandleRect::RightTop:
        return Qt::SizeBDiagCursor;
    case SizeHandleRect::RightBottom:
        return Qt::SizeFDiagCursor;
    case SizeHandleRect::LeftBottom:
        return Qt::SizeBDiagCursor;
    case SizeHandleRect::Bottom:
        return Qt::SizeVerCursor;
    case SizeHandleRect::LeftTop:
        return Qt::SizeFDiagCursor;
    case SizeHandleRect::Left:
        return Qt::SizeHorCursor;
    case SizeHandleRect::Top:
        return Qt::SizeVerCursor;
    default:
        break;
    }
    return Qt::ArrowCursor;
}

SizeHandleRect::Direction GraphicsRectItem::hitTest(const QPointF &point) const
{
    const Handles::const_iterator hend =  m_handles.end();
    for (Handles::const_iterator it = m_handles.begin(); it != hend; ++it)
    {
        if ((*it)->hitTest(point) ){
            return (*it)->dir();
        }
    }
    return SizeHandleRect::None;
}

void GraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen =painter->pen();
    pen.setWidth(4);
    pen.setColor(QColor(255, 0, 0));
    painter->setPen(pen);
    painter->drawRect(rect());
}

void GraphicsRectItem::updateGeometry()
{
    const QRectF &rect = this->boundingRect();

    const Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it) {
        SizeHandleRect *hndl = *it;;
        switch (hndl->dir()) {
        case SizeHandleRect::LeftTop:
            hndl->move(rect.x() - selection_handle_size / 2, rect.y() - selection_handle_size / 2);
            break;
        case SizeHandleRect::Top:
            hndl->move(rect.x() + rect.width() / 2 - selection_handle_size / 2, rect.y() - selection_handle_size / 2);
            break;
        case SizeHandleRect::RightTop:
            hndl->move(rect.x() + rect.width() - selection_handle_size / 2, rect.y() - selection_handle_size / 2);
            break;
        case SizeHandleRect::Right:
            hndl->move(rect.x() + rect.width() - selection_handle_size / 2, rect.y() + rect.height() / 2 - selection_handle_size / 2);
            break;
        case SizeHandleRect::RightBottom:
            hndl->move(rect.x() + rect.width() - selection_handle_size / 2, rect.y() + rect.height() - selection_handle_size / 2);
            break;
        case SizeHandleRect::Bottom:
            hndl->move(rect.x() + rect.width() / 2 - selection_handle_size / 2, rect.y() + rect.height() - selection_handle_size / 2);
            break;
        case SizeHandleRect::LeftBottom:
            hndl->move(rect.x() - selection_handle_size / 2, rect.y() + rect.height() - selection_handle_size / 2);
            break;
        case SizeHandleRect::Left:
            hndl->move(rect.x() - selection_handle_size / 2, rect.y() + rect.height() / 2 - selection_handle_size / 2);
            break;
        case SizeHandleRect::Center:
            hndl->move(rect.center().x()  - selection_handle_size / 2 , rect.center().y() - selection_handle_size / 2);
            break;
        default:
            break;
        }
    }
}

QRectF GraphicsRectItem::rect() const
{
    return QRectF(QPointF(m_rect.left(),m_rect.top()),
                  QPointF(m_rect.right(), m_rect.bottom()));
}

void GraphicsRectItem::setState(SelectionHandleState st)
{
    const Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it)
        (*it)->setState(st);
}

QVariant GraphicsRectItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if ( change == QGraphicsItem::ItemSelectedHasChanged ) {
        qDebug()<<" Item Selected : " << value.toString();
        setState(value.toBool() ? SelectionHandleActive : SelectionHandleOff);
    }else if ( change == QGraphicsItem::ItemRotationHasChanged ){
        qDebug()<<"Item Rotation Changed:" << value.toString();
    }else if ( change == QGraphicsItem::ItemTransformOriginPointHasChanged ){
        qDebug()<<"ItemTransformOriginPointHasChanged:" << value.toPointF();
    }
    return value;
}

QRectF GraphicsRectItem::boundingRect() const
{
    return rect();
}

graphicsscene.cpp

#include "graphicsscene.h"
#include <QGraphicsView>
#include <QDebug>

enum SelectMode
{
    none,
    netSelect,
    move, //移动
    size, //改变大小
    rotate //反转
};

SelectMode selectMode = none;

SizeHandleRect::Direction nDragHandle = SizeHandleRect::None;

GraphicsScene::GraphicsScene()
{

}

void GraphicsScene::creatRect()
{
//    if(m_RectItem){
//        return;
//    }
    this->clearSelection();
    m_RectItem = new GraphicsRectItem(QRect(0, 0, 200, 100), NULL);
    this->addItem(m_RectItem);
    m_RectItem->setSelected(true);
    this->update();
}

void GraphicsScene::SetBackGroundImage(QPixmap pix, int width, int height)
{
    this->clear();
    QGraphicsPixmapItem* _backGroundItem= this->addPixmap(pix);

    qreal scale = 0.0;
    if((double)width/height > (double)pix.width()/pix.height()){
        scale = (double)height/pix.height();
    } else{
        scale = (double)width/pix.width();
    }

    _backGroundItem->setScale(scale);

//    _backGroundItem->setPos(0,0);
}

void GraphicsScene::setCursor(const QCursor &cursor)
{
    QList<QGraphicsView*> views  = this->views();
    if ( views.count() > 0 ){
        QGraphicsView * view = views.first();
        view->setCursor(cursor);
    }
}

void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QList<QGraphicsItem *> items = this->selectedItems();
    GraphicsRectItem *item = 0;
    if ( items.count() == 1 )
    {
        item = qgraphicsitem_cast<GraphicsRectItem*>(items.first());

        nDragHandle = item->hitTest(event->scenePos());
        if ( nDragHandle !=SizeHandleRect::None)
            selectMode = size;
        else
            selectMode =  move;
    }
    if(selectMode == move || selectMode == none){
        QGraphicsScene::mousePressEvent(event);
    }
}

void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QList<QGraphicsItem *> items = this->selectedItems();
    if(items.count() == 1){
        GraphicsRectItem *item = qgraphicsitem_cast<GraphicsRectItem*>(items.first());
        if ( nDragHandle != SizeHandleRect::None && selectMode == size ){
            item->resizeTo(nDragHandle,event->scenePos());
        }
        else if(nDragHandle == SizeHandleRect::None && selectMode == none ){


            SizeHandleRect::Direction handle = item->hitTest(event->scenePos());
            if ( handle != SizeHandleRect::None){
                setCursor(item->getCursor(handle));
            }else{
                setCursor(Qt::ArrowCursor);
            }
        }
        else if(nDragHandle == SizeHandleRect::None && selectMode == move ){

            item->move(event->scenePos());
        }
    }

    this->update();
}

void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    setCursor(Qt::ArrowCursor);
    selectMode = none;
    nDragHandle = SizeHandleRect::None;
    QGraphicsScene::mouseReleaseEvent(event);
}

graphicsview.cpp

#include "graphicsview.h"

GraphicsView::GraphicsView(QWidget *parent) :
    QGraphicsView(parent)
{
    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    this->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}

void GraphicsView::keyPressEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case Qt::Key_Plus :
        scale(1.2, 1.2);
        break;
    case Qt::Key_Minus :
        scale(1 / 1.2, 1 / 1.2);
        break;
    case Qt::Key_Right :
        rotate(30);
        break;
    }
    QGraphicsView::keyPressEvent(event);
}

void GraphicsView::wheelEvent(QWheelEvent *event)
{
    // 滚轮的滚动量
    QPoint scrollAmount = event->angleDelta();
    // 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小)
    scrollAmount.y() > 0 ? scale(1.2, 1.2) : scale(1 / 1.2, 1 / 1.2);
}

sizehandlerect.cpp

#include "sizehandlerect.h"
#include <QPainter>

SizeHandleRect::SizeHandleRect(QGraphicsItem *parent, QRectF rect, Direction dir) :
    QGraphicsRectItem(rect, parent),
    m_dir(dir),
    m_state(SelectionHandleOff)
{
    setParentItem(parent);
    hide();
}

SizeHandleRect::Direction SizeHandleRect::dir() const
{
    return m_dir;
}

bool SizeHandleRect::hitTest(const QPointF &point)
{
    QPointF pt = mapFromScene(point);
    return rect().contains(pt);
}

void SizeHandleRect::move(qreal x, qreal y)
{
    setPos(x,y);
}

void SizeHandleRect::setState(SelectionHandleState st)
{
    if (st == m_state)
        return;
    switch (st) {
    case SelectionHandleOff:
        hide();
        break;
    case SelectionHandleInactive:
    case SelectionHandleActive:
        show();
        break;
    }
    m_state = st;
}

void SizeHandleRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QColor c = QColor("limegreen");
  //  c.setAlpha(200);
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(c));

    painter->drawRect(rect());
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    scene = new GraphicsScene();

    ui->graphicsView->setScene(scene);
    scene->addItem(new GraphicsRectItem(QRect(-1, -1, 3, 3), NULL));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_createRect_clicked()
{
    scene->creatRect();
}

void MainWindow::on_pushButton_getRect_clicked()
{

    if(scene->m_RectItem){
//        QPoint point = scene->m_RectItem->m_rect.topLeft();
        QRect rect = scene->m_RectItem->rect().toRect();
        ui->lineEdit->setText("x:" + QString::number(rect.topLeft().x()) + "  y:" + QString::number(rect.topLeft().y())
                              + "  w:" + QString::number(rect.width()) + "  h:" + QString::number(rect.height()));

    }
}

void MainWindow::on_pushButton_addPix_clicked()
{
    QPixmap pix("D:/imageprocess/111111111GraphicsRectDemo/img.bmp");
//    QPixmap pix("img.jpg");
    scene->SetBackGroundImage(pix, ui->graphicsView->width(), ui->graphicsView->height());
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI炮灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值