Pedro Monteiro
Pedro Monteiro

Reputation: 357

Restrict item in PyQt4‏ using itemChange()

I tried using the Qt documentation example to restrict the rectangle to the area of the scene but it still fails, someone has an alternative to do this?

My code, the QGraphicsView instance was created in Qt Desginer:

# -*- coding: utf-8 -*-

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
from screen import *

class MovableItem(QGraphicsRectItem):
    def __init__(self, rectang, *args, **kwargs):
        QGraphicsRectItem.__init__(self, rectang, *args, **kwargs)
        self.setFlags(QGraphicsItem.ItemIsMovable |
                  QGraphicsItem.ItemSendsGeometryChanges)

        self.pen = QPen(Qt.darkMagenta)
        self.pen.setWidth(4)

        self.setPen(self.pen)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange and self.scene():
            # value is the new position.
            self.newPos = value.toPointF()
            self.rect = self.scene().sceneRect()

            if not(self.rect.contains(self.newPos)):
            # Keep the item inside the scene rect.
                self.newPos.setX(min(self.rect.right(), max(self.newPos.x(), self.rect.left())))
                self.newPos.setY(min(self.rect.bottom(), max(self.newPos.y(), self.rect.top())))

                return self.newPos

        return QGraphicsRectItem.itemChange(self, change, value)


class Main(QWidget, Ui_Form):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)

        self.scene = QGraphicsScene()
        self.cena.setScene(self.scene)
        self.scene.addPixmap(QPixmap("01.png"))

        self. graph = MovableItem(2, 2, 300, 150)

        self.scene.addItem(self.graph)

    def showEvent(self, event):
        self.cena.fitInView(self.scene.sceneRect(), Qt.IgnoreAspectRatio)


app = QApplication(sys.argv)
window = Main()
window.show()

sys.exit(app.exec_())

Upvotes: 1

Views: 582

Answers (1)

Pedro J
Pedro J

Reputation: 148

First:

Use setSceneRect() in your main Main(), to set the size of the scene.

Second:

Actually the example of the documentation is wrong, therefore, to adjust the rectangle to the scene, delete this if and subtract, in min, the parameters right and bottom by the rectangle dimensions right and bottom in setX and setY. Replace this part of your code:

if not(self.rect.contains(self.newPos)):
# Keep the item inside the scene rect.
    self.newPos.setX(min(self.rect.right(), max(self.newPos.x(), self.rect.left())))
    self.newPos.setY(min(self.rect.bottom(), max(self.newPos.y(), self.rect.top())))

    return self.newPos

For:

self.newPos.setX(min(self.rect.right()-self.boundingRect().right(), max(self.newPos.x(), self.rect.left())))
self.newPos.setY(min(self.rect.bottom()-self.boundingRect().bottom(), max(self.newPos.y(), self.rect.top())))

return self.newPos

Upvotes: 1

Related Questions