Qt :QGraphicsScene管理QGraphicsItem(单击/选择/移动/缩放/删除)

发布时间 2023-09-08 00:04:01作者: imxiangzi

 

本文转载大神作者:一去丶二三里 博客地址:http://blog.csdn.net/liang19890820.

简述

在图形视图框架中,QGraphicsScene 提供一个快速的接口,用于管理大量 item,QGraphicsItem 是场景中 item 的基类。

图形视图提供了一些典型形状的标准 item,当然,我们也可以自定义 item。除此之外,QGraphicsItem 还支持以下特性:

鼠标按下、移动、释放和双击事件,以及鼠标悬浮事件、滚轮事件和上下文菜单事件 

键盘输入焦点和键盘事件 

拖放 

分组:通过父子关系,或 QGraphicsItemGroup 

碰撞检测 

下面,一起来看看 QGraphicsScene 对 QGraphicsItem 的管理,主要包括:单击、选择、移动、缩放、删除等。

简述 

操作细节 

示例 

效果 

源码 

操作细节

为了实现以上功能,我们主要实现了 QGraphicsScene 和 QGraphicsItem 对应的事件,通过鼠标和键盘来操作。

操作细节主要包括:

选择:点击左键、按 Shift 键可以单选,按下 Ctrl 可进行多选。 

添加:点击左键 

删除:点击右键,删除鼠标下的 item;当按下 Ctrl 选择多个 items 时,按下 Backspace 键,将选中的全部删除。 

移动:点击左键,选择 item,然后移动鼠标;当按下 Ctrl 选择多个 items 时,可以移动选中的 items。 

缩放:按 Alt 键,然后鼠标拖拽 item 的边界。 

在对应操作的事件中,我们输出了一些调试信息,以便跟踪。

 

源码

custom_item.h:

#ifndef CUSTOM_ITEM_H

#define CUSTOM_ITEM_H

 

#include <QGraphicsRectItem>

#include <QGraphicsScene>

 

//QGraphicsScene管理QGraphicsItem(单击/选择/移动/缩放/删除)

// 自定义 Item

class CustomItem : public QGraphicsRectItem

{

public:

    explicit CustomItem(QGraphicsItem *parent = 0);

protected:

    // Shift+左键:进行选择  Alt:准备缩放

    void mousePressEvent(QGraphicsSceneMouseEvent *event);

    // Alt+拖拽:进行缩放  移动

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

    // 使item可使用qgraphicsitem_cast

    int type() const;

private:

    QPointF m_centerPointF;

    bool m_bResizing;

};

 

// 自定义 Scene

class CustomScene : public QGraphicsScene

{

protected:

    // 左键:添加item  右键:移除item

    void mousePressEvent(QGraphicsSceneMouseEvent *event);

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

    // Backspace键移除item

    void keyPressEvent(QKeyEvent *event);

};

 

#endif // CUSTOM_ITEM_H

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

custom_item.cpp:

#include <QKeyEvent>

#include <QGraphicsSceneMouseEvent>

#include <QDebug>

#include "custom_item.h"

 

// 自定义 Item

CustomItem::CustomItem(QGraphicsItem *parent)

    : QGraphicsRectItem(parent)

{

    // 画笔 - 边框色

    QPen p = pen();

    p.setWidth(2);

    p.setColor(QColor(0, 160, 230));

 

    setPen(p);

    // 画刷 - 背景色

    setBrush(QColor(247, 160, 57));

 

    // 可选择、可移动

    setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);

}

 

void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event)

{

    if (event->button() == Qt::LeftButton) {

        if (event->modifiers() == Qt::ShiftModifier) {

            qDebug() << "Custom item left clicked with shift key.";

            // 选中 item

            setSelected(true);

        } else if (event->modifiers() == Qt::AltModifier) {

            qDebug() << "Custom item left clicked with alt key.";

            // 重置 item 大小

            double radius = boundingRect().width() / 2.0;

            QPointF topLeft = boundingRect().topLeft();

            m_centerPointF = QPointF(topLeft.x() + pos().x() + radius, topLeft.y() + pos().y() + radius);

            QPointF pos = event->scenePos();

            qDebug() << boundingRect() << radius << this->pos() << pos << event->pos();

            double dist = sqrt(pow(m_centerPointF.x()-pos.x(), 2) + pow(m_centerPointF.y()-pos.y(), 2));

            if (dist / radius > 0.8) {

                qDebug() << dist << radius << dist / radius;

                m_bResizing = true;

            } else {

                m_bResizing = false;

            }

        } else {

            qDebug() << "Custom item left clicked.";

            QGraphicsItem::mousePressEvent(event);

            event->accept();

        }

    } else if (event->button() == Qt::RightButton) {

        qDebug() << "Custom item right clicked.";

        event->ignore();

    }

}

 

void CustomItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)

{

    if ((event->modifiers() == Qt::AltModifier) && m_bResizing) {

        QPointF pos = event->scenePos();

        double dist = sqrt(pow(m_centerPointF.x()-pos.x(), 2) + pow(m_centerPointF.y()-pos.y(), 2));

        setRect(m_centerPointF.x()-this->pos().x()-dist, m_centerPointF.y()-this->pos().y()-dist, dist*2, dist*2);

    } else if(event->modifiers() != Qt::AltModifier) {

        qDebug() << "Custom item moved.";

        QGraphicsItem::mouseMoveEvent(event);

        qDebug() << "moved" << pos();

    }

}

 

void CustomItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)

{

    if ((event->modifiers() == Qt::AltModifier) && m_bResizing) {

        m_bResizing = false;

    } else {

        QGraphicsItem::mouseReleaseEvent(event);

    }

}

 

int CustomItem::type() const

{

    return UserType + 1;

}

 

// 自定义 Scene

void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event)

{

    qDebug() << "Custom scene clicked.";

    QGraphicsScene::mousePressEvent(event);

    if (!event->isAccepted()) {

        if (event->button() == Qt::LeftButton) {

            // 在 Scene 上添加一个自定义 item

            QPointF point = event->scenePos();

            CustomItem *item = new CustomItem();

            item->setRect(point.x()-25, point.y()-25, 60, 60);

            addItem(item);

        } else if (event->button() == Qt::RightButton) {

            // 检测光标下是否有 item

            QGraphicsItem *itemToRemove = NULL;

            foreach (QGraphicsItem *item, items(event->scenePos())) {

                if (item->type() == QGraphicsItem::UserType+1) {

                    itemToRemove = item;

                    break;

                }

            }

            // 从 Scene 上移除 item

            if (itemToRemove != NULL)

                removeItem(itemToRemove);

        }

    }

}

 

void CustomScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)

{

    qDebug() << "Custom scene moved.";

    QGraphicsScene::mouseMoveEvent(event);

}

 

void CustomScene::keyPressEvent(QKeyEvent *event) {

    if (event->key() == Qt::Key_Backspace) {

        // 移除所有选中的 items

        qDebug() << "selected items " << selectedItems().size();

        while (!selectedItems().isEmpty()) {

            removeItem(selectedItems().front());

        }

    } else {

        QGraphicsScene::keyPressEvent(event);

    }

}

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127

使用很简单,将 item 添加至 scene 中,通过 view 显示即可。

#include <QApplication>

#include <QGraphicsView>

#include "custom_item.h"

 

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

 

    // 创建 item

    CustomItem *pItem = new CustomItem();

    pItem->setRect(20, 20, 60, 60);

 

    // 将 item 添加至场景中

    CustomScene scene;

    scene.setSceneRect(0, 0, 400, 300);

    scene.addItem(pItem);

 

    // 为视图设置场景

    QGraphicsView view;

    view.setScene(&scene);

    view.show();

 

    return a.exec();

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

本文转载大神作者:一去丶二三里 博客地址:http://blog.csdn.net/liang19890820.

 

 

from:https://blog.csdn.net/qq_37233607/article/details/79343891