QGrphicsScen画布网格和QGrphicsItem对齐到网格

cpp 复制代码
#include <QGraphicsScene>
#include <QPainter>
#include <QWheelEvent>
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
public:
    MyGraphicsView(QGraphicsScene* scene) : QGraphicsView(scene)
    {

    }

protected:
    // 重写滚轮事件,实现缩放
    void wheelEvent(QWheelEvent* event) override
    {
        // 使用滚轮进行缩放
        if (event->angleDelta().y() > 0)
            scale(1.2, 1.2);  // 放大
        else
            scale(0.8, 0.8);  // 缩小
    }
};
class GridScene : public QGraphicsScene {
public:
    GridScene(QObject* parent = nullptr) : QGraphicsScene(parent), gridSize(20) {}

    void setGridSize(int size) {
        gridSize = size;
        update();
    }

    int gridSize1() const { return gridSize; }

protected:
    void drawBackground(QPainter* painter, const QRectF& rect) override {
        QGraphicsScene::drawBackground(painter, rect);

        // 绘制网格
        qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
        qreal top = int(rect.top()) - (int(rect.top()) % gridSize);

        QVector<QLineF> lines;
        for (qreal x = left; x < rect.right(); x += gridSize) {
            lines.append(QLineF(x, rect.top(), x, rect.bottom()));
        }
        for (qreal y = top; y < rect.bottom(); y += gridSize) {
            lines.append(QLineF(rect.left(), y, rect.right(), y));
        }

        painter->setPen(QPen(QColor(200, 200, 200), 1));
        painter->drawLines(lines.data(), lines.size());
    }

private:
    int gridSize;
};

#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>

class SnapItem : public QGraphicsItem {
public:
    SnapItem(QGraphicsItem* parent = nullptr) : QGraphicsItem(parent) {
        setFlag(QGraphicsItem::ItemIsMovable);
        setFlag(QGraphicsItem::ItemSendsGeometryChanges);
    }

    QRectF boundingRect() const override {
        return QRectF(122, 432, 64, 102); // 示例大小
    }

    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override {
        painter->setBrush(Qt::blue);
        painter->drawRect(boundingRect());
    }

protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant& value) override {
        if (change == ItemPositionChange && scene()) {
            // 获取场景中的网格大小
            GridScene* gridScene = dynamic_cast<GridScene*>(scene());
            if (gridScene) {
                int gridSize = gridScene->gridSize1();

                QPointF newPos = value.toPointF();
                QRectF bounds = boundingRect();
                QPointF offset = bounds.topLeft();

                QPointF renderPos = newPos + offset;
                qreal xV = round(renderPos.x() / gridSize) * gridSize - offset.x();
                qreal yV = round(renderPos.y() / gridSize) * gridSize - offset.y();

                return QPointF(xV, yV);
            }
        }
        return QGraphicsItem::itemChange(change, value);
    }
};

#include <QApplication>
#include <QGraphicsView>

int main(int argc, char* argv[]) {
    QApplication a(argc, argv);

    // 创建场景和视图
    GridScene scene;
    scene.setSceneRect(0, 0, 800, 600);
    scene.setGridSize(57); // 设置网格大小

    MyGraphicsView view(&scene);
    view.setRenderHint(QPainter::Antialiasing);
    view.setDragMode(QGraphicsView::RubberBandDrag);
    view.show();

    // 添加一些可吸附的item
    /*for (int i = 0; i < 5; ++i) {
        SnapItem* item = new SnapItem();
        item->setPos(i * 100, i * 100);
        scene.addItem(item);
    }*/
    SnapItem* item = new SnapItem();
    item->setPos(122, 57);
    scene.addItem(item);

    SnapItem* item1 = new SnapItem();
    item1->setPos(133, 87);
    scene.addItem(item1);

    SnapItem* item2 = new SnapItem();
    item2->setPos(234, 97);
    scene.addItem(item2);
    return a.exec();
}

重写QGrphicsItem得itemChange方法即可实现对齐吸附到网格线,类似于ppt中得效果。

相关推荐
東隅已逝,桑榆非晚16 分钟前
算法3.双指针法-快乐数
c++·笔记·学习·算法
lhbweilai1 小时前
QT项目(串口助手)
开发语言·qt
eggwyw1 小时前
C++相交链表和反转链表详解
开发语言·c++
杜 硕1 小时前
从零开始的C++生活——第六讲——02
c++·算法·生活
小超人诞生日记1 小时前
C++ STL 反向迭代器:从源码框架到适配器实现
c++·算法
青少儿编程课堂1 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园成语接龙大挑战解析
c++·python·算法·bfs·信息学竞赛
小贾要学习1 小时前
【C++后端开发项目】Reactor 模型 / C++ 仿写 muduo HTTP 服务器:让底层网络库真正跑起网页
linux·服务器·c++·http·网络编程·muduo·reactor模型
A7bert7772 小时前
【MobileSAM部署至RK3588】环境适配→转换RKNN→开发板部署
c++·人工智能·深度学习·目标检测·ubuntu
青少儿编程课堂3 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:分层图最短路解析
c++·python·算法·bfs·信息学竞赛
FlightYe13 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频