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

来源:互联网 发布:hbuilder下载 mac版 编辑:程序博客网 时间:2024/06/06 03:45


来源:http://blog.csdn.net/liang19890820/article/details/53504323


简述

在图形视图框架中,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(单击/选择/移动/缩放/删除)// 自定义 Itemclass 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;};// 自定义 Sceneclass 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
  • 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"// 自定义 ItemCustomItem::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;}// 自定义 Scenevoid 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
  • 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24



0 0
原创粉丝点击