1

I have implemented grid in graphicsView using drawBackgroud method. Now I also want to add snap to the grid. By snap I mean that with mouse, you can't have point other than grid points. My code to grid drawn is as follows:

void CadGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
{
    const int gridSize = 50;
    const int realLeft = static_cast<int>(std::floor(rect.left()));
    const int realRight = static_cast<int>(std::ceil(rect.right()));
    const int realTop = static_cast<int>(std::floor(rect.top()));
    const int realBottom = static_cast<int>(std::ceil(rect.bottom()));

    // Draw grid.
    const int firstLeftGridLine = realLeft - (realLeft % gridSize);
    const int firstTopGridLine = realTop - (realTop % gridSize);
    QVarLengthArray<QLine, 100> lines;

    for (qreal x = firstLeftGridLine; x <= realRight; x += gridSize)
        lines.append(QLine(x, realTop, x, realBottom));
    for (qreal y = firstTopGridLine; y <= realBottom; y += gridSize)
        lines.append(QLine(realLeft, y, realRight, y));

    painter->setPen(QPen(QColor(220, 220, 220), 0.0));
    painter->drawLines(lines.data(), lines.size());

    // Draw axes.
    painter->setPen(QPen(Qt::lightGray, 0.0));
    painter->drawLine(0, realTop, 0, realBottom);
    painter->drawLine(realLeft, 0, realRight, 0);
}

Please help me solve the problem and complete the task.


I tried to do it using itemChange method but nothing happened:

My code to it is as follows: snap.cpp

 #include "snap.h"
#include <QApplication>

    Snap::Snap(const QRect& rect, QGraphicsItem* parent,
               QGraphicsScene* scene):
    QGraphicsRectItem(QRectF())
    {
        setFlags(QGraphicsItem::ItemIsSelectable |
                QGraphicsItem::ItemIsMovable |
                QGraphicsItem::ItemSendsGeometryChanges);
    }

    void Snap::mousePressEvent(QGraphicsSceneMouseEvent *event){
        offset = pos() - computeTopLeftGridPoint(pos());
        QGraphicsRectItem::mousePressEvent(event);
    }

    QVariant Snap::itemChange(GraphicsItemChange change,
    const QVariant &value)
    {
        if (change == ItemPositionChange && scene()) {
            QPointF newPos = value.toPointF();
            if(QApplication::mouseButtons() == Qt::LeftButton &&
                qobject_cast<CadGraphicsScene*> (scene())){
                    QPointF closestPoint = computeTopLeftGridPoint(newPos);
                    return closestPoint+=offset;
                }
            else
                return newPos;
        }
        else
            return QGraphicsItem::itemChange(change, value);
    }

    QPointF Snap::computeTopLeftGridPoint(const QPointF& pointP){
       CadGraphicsScene* customScene = qobject_cast<CadGraphicsScene*> (scene());
        int gridSize = customScene->getGridSize();
        qreal xV = floor(pointP.x()/gridSize)*gridSize;
        qreal yV = floor(pointP.y()/gridSize)*gridSize;
        return QPointF(xV, yV);
    }

snap.h

#ifndef SNAP_H
#define SNAP_H

#include <QGraphicsRectItem>
#include "cadgraphicsscene.h"

class Snap : public QGraphicsRectItem
{
public:
    Snap(const QRect& rect, QGraphicsItem* parent,
         QGraphicsScene* scene);
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    QVariant itemChange(GraphicsItemChange change,
    const QVariant &value);
private:
    QPointF offset;
    QPointF computeTopLeftGridPoint(const QPointF &pointP);
};

#endif // SNAP_H

Please help me out to snap to grid.

user3859872
  • 777
  • 2
  • 9
  • 16
  • Create your own move function for your graphics items, where you check what is the closest grid point to the move point, or which grid contains the move point and move the item to that point. – thuga Nov 17 '14 at 12:14
  • It's just simple math. You try to move your item to the point x1,y1.. you calculate in which grid cell the point x1,y1 is inside.. then you just move the item to the point x2,y2, which would be the cell's top left corner. You know the grid's cell height and width so it is not hard to calculate. – thuga Nov 17 '14 at 12:53
  • What type is `CadGraphicsView`? – thuga Nov 24 '14 at 07:14
  • CadGraphicsView is a class in which all the items drawn are called. – user3859872 Nov 24 '14 at 09:32
  • The error was solved now getting different error unable to get the error. The error is regarding the declaration of function. Please help me to solve the error. – user3859872 Nov 24 '14 at 11:07
  • Well the error message is obvious. `QGraphicsRectItem` doesn't have such constructor you're trying to call: `QGraphicsRectItem::QGraphicsRectItem(const QRect&, QGraphicsItem*&, QGraphicsScene*&)`. Check the [docs](http://qt-project.org/doc/qt-5/qgraphicsrectitem.html) to see what constructors `QGraphicsRectItem` does have. – thuga Nov 24 '14 at 11:19
  • You don't have to pass anything. `QGraphicsRectItem` has a constructor that doesn't expect any parameters. Or you can pass a `QRectF`. Look at the docs, and pick a constructor that suits your needs. You don't have to pass all the parameters to the base constructor that you pass to the derived class. – thuga Nov 24 '14 at 13:22
  • Run in debug mode and see where it crashes. You'll most likely find out why as well. – thuga Nov 25 '14 at 07:32
  • 3
    Instead of editing the question all the time so the context changes completely, ask a new question. – thuga Nov 27 '14 at 10:19

0 Answers0