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

本文转载大神作者:一去丶二三里 博客地址: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

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);
    }
}

使用很简单,将 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();
}

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

要用QtQGraphicsSceneQGraphicsItem与QGraphicsView绘制板块热力图,需要按照以下步骤进行: 1. 创建一个QGraphicsScene对象,用于管理图形项。 2. 创建一个QGraphicsView对象,将QGraphicsScene作为参数传递给它。 3. 创建一个QGraphicsItem对象,用于绘制热力图。 4. 在QGraphicsItem的paint()函数中,使用QPainter对象绘制热力图。 5. 将QGraphicsItem添加到QGraphicsScene中。 6. 将QGraphicsView添加到Qt应用程序的主窗口中。 下面是一个简单的代码示例,用于绘制一个矩形的热力图: ```cpp // 创建QGraphicsScene对象 QGraphicsScene* scene = new QGraphicsScene(this); // 创建QGraphicsView对象,并将QGraphicsScene作为参数传递给它 QGraphicsView* view = new QGraphicsView(scene, this); // 创建QGraphicsItem对象,用于绘制热力图 class HeatmapItem : public QGraphicsItem { public: HeatmapItem() : QGraphicsItem() {} QRectF boundingRect() const override { return QRectF(0, 0, 100, 100); } void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override { Q_UNUSED(option) Q_UNUSED(widget) // 创建渐变色 QLinearGradient gradient(0, 0, 0, 100); gradient.setColorAt(0, QColor(255, 0, 0)); gradient.setColorAt(0.5, QColor(255, 255, 0)); gradient.setColorAt(1, QColor(0, 255, 0)); // 绘制矩形 painter->setBrush(gradient); painter->drawRect(boundingRect()); } }; HeatmapItem* heatmap = new HeatmapItem(); scene->addItem(heatmap); // 将QGraphicsView添加到主窗口中 view->setGeometry(0, 0, 300, 300); view->show(); ``` 在上面的示例中,我们使用QGraphicsItem绘制了一个矩形的热力图,并将它添加到了QGraphicsScene中。然后,我们创建了一个QGraphicsView对象,并将QGraphicsScene作为参数传递给它。最后,我们将QGraphicsView添加到了主窗口中,显示了热力图。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值