restrict movable area of qgraphicsitem
Asked Answered
B

3

7

Is there a way to restrict the area where a QGraphicsItem like QRect can be moved when setFlag(ItemIsMovable) is set?

I'm new to pyqt and trying to find a way to move an item with the mouse, and the restrict it to only vertically/horizontally.

Blessington answered 23/8, 2010 at 13:59 Comment(0)
C
7

If you want to keep a limited area you can reimplement the ItemChanged()

Declare:

#ifndef GRAPHIC_H
#define GRAPHIC_H
#include <QGraphicsRectItem>
class Graphic : public QGraphicsRectItem
{
public:
    Graphic(const QRectF & rect, QGraphicsItem * parent = 0);
protected:
    virtual QVariant    itemChange ( GraphicsItemChange change, const QVariant & value );
};

#endif // GRAPHIC_H

implementation : ItemSendsGeometryChanges flag is needed to capture the change in position of QGraphicsItem

#include "graphic.h"
#include <QGraphicsScene>

Graphic::Graphic(const QRectF & rect, QGraphicsItem * parent )
    :QGraphicsRectItem(rect,parent)
{
    setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges);
}

QVariant Graphic::itemChange ( GraphicsItemChange change, const QVariant & value )
{
    if (change == ItemPositionChange && scene()) {
        // value is the new position.
        QPointF newPos = value.toPointF();
        QRectF rect = scene()->sceneRect();
        if (!rect.contains(newPos)) {
            // Keep the item inside the scene rect.
            newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
            newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
            return newPos;
        }
    }
    return QGraphicsItem::itemChange(change, value);
}

Then we define the rectangle of the scene, in this case will be 300x300

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QGraphicsView * view = new QGraphicsView(this);
    QGraphicsScene * scene = new QGraphicsScene(view);
    scene->setSceneRect(0,0,300,300);
    view->setScene(scene);
    setCentralWidget(view);
    resize(400,400);

    Graphic * graphic = new Graphic(QRectF(0,0,100,100));
    scene->addItem(graphic);
    graphic->setPos(150,150);

}

This is to keep the graph within an area, good luck

Chute answered 5/11, 2011 at 5:18 Comment(1)
It works very well, expect the Graphic item CAN be dragged a little bit outside the scene in the right & bottom area, because you are using the top-left coordinates of the Graphic box to verify if the object is inside the scene rect.Maloney
B
4

re implement the mouseMoveEvent(self,event) in the QGraphicScene like the following :

def mousePressEvent(self, event ):

    self.lastPoint = event.pos()

def mouseMoveEvent(self, point):

    if RestrictedHorizontaly: # boolean to trigger weather to restrict it horizontally 
        x = point.x()
        y = self.lastPoint.y()
        self.itemSelected.setPos(QtCore.QPointF(x,y))<br> # which is the QgraphicItem that you have or selected before

hope it helps

Bifrost answered 22/9, 2010 at 12:46 Comment(0)
T
1

You would probably need to re-implement the QGraphicsItem's itemChange() function.

Pseudocode:

if (object position does not meet criteria):
    (move the item so its position meets criteria)

Repositioning the item will cause itemChange to get called again, but that's ok because the item will be positioned correctly and won't be moved again, so you'll not be stuck in an endless loop.

Taper answered 24/8, 2010 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.