I’m writing an application in PyQt5 that will allow the user to rotate a QGraphicsPixmapItem and also delete it. The rotation needs to be with the mouse via a rotation handle that the user can grab with the mouse and rotate, thus rotating the QGraphicsPixmapItem. I need the handle to have a fixed distance to the item position, precisely to be at the top left corner of the QGraphicsPixmapItem. Also, I need the handle to be a child of the graphic pixmap item so that when the user moves the image or deletes it, the handle will be moved or deleted too.
I based my code on this answer https://stackoverflow.com/questions/...tem-with-mouse
I have some troubles, when I do not set the handle as a child of the graphic pixmap item, the rotation is fine but not the part of moving the handle when the user moves the image. When I set the handle as a child, the rotation doesn’t work as I want.
Could someone help me please? This is my code:

Qt Code:
  1. import sys
  2. from PyQt5.QtWidgets import QMainWindow, QApplication, QGraphicsView
  3. from PyQt5 import QtGui, QtWidgets
  4. import math
  5.  
  6. class MainWindow(QMainWindow):
  7. def __init__(self, parent=None):
  8. super(MainWindow, self).__init__(parent)
  9.  
  10. self.scene = Scene()
  11. self.view = QGraphicsView(self)
  12. self.setGeometry(10, 30, 850, 600)
  13. self.view.setGeometry(20, 22, 800, 550)
  14. self.view.setScene(self.scene)
  15.  
  16. class Scene(QtWidgets.QGraphicsScene):
  17. def __init__(self, parent=None):
  18. super(Scene, self).__init__(parent)
  19. # other stuff here
  20. self.set_image()
  21.  
  22. def set_image(self):
  23. photo = Photo()
  24. self.addItem(photo)
  25. photo.set_pixmap()
  26.  
  27. class Photo(QtWidgets.QGraphicsPixmapItem):
  28. def __init__(self, parent=None):
  29. super(Photo, self).__init__(parent)
  30.  
  31. self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
  32. self.setTransformOriginPoint(self.boundingRect().center())
  33.  
  34. def set_pixmap(self):
  35. pixmap = QtGui.QPixmap("perro.jpg")
  36. self.setPixmap(pixmap)
  37. self.pixmap_controller = PixmapController(self)
  38. self.pixmap_controller.set_pixmap_controller()
  39. self.pixmap_controller.setPos(self.boundingRect().topLeft())
  40. self.pixmap_controller.setFlag(QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges, True)
  41.  
  42. def rotate_item(self, position):
  43. item_position = self.transformOriginPoint()
  44. angle = math.atan2(item_position.y() - position.y(), item_position.x() - position.x()) / math.pi * 180 - 45
  45. print(angle)
  46. self.setRotation(angle)
  47. self.setPos(position)
  48.  
  49. class PixmapController(QtWidgets.QGraphicsEllipseItem):
  50. def __init__(self, pixmap):
  51. super(PixmapController, self).__init__(parent=pixmap)
  52. self.pixmap = pixmap
  53.  
  54. self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
  55. color = QtGui.QColor(0, 0, 0)
  56. brush = QtGui.QBrush(color)
  57. self.setBrush(brush)
  58.  
  59. def set_pixmap_controller(self):
  60. self.setRect(-5, -5, 10, 10)
  61.  
  62. def itemChange(self, change, value):
  63. if change == QtWidgets.QGraphicsItem.ItemPositionChange:
  64. self.pixmap.rotate_item(value)
  65. return super(PixmapController, self).itemChange(change, value)
  66.  
  67. if __name__ == "__main__":
  68. app = QApplication(sys.argv)
  69. window = MainWindow()
  70. window.show()
  71. sys.exit(app.exec_())
To copy to clipboard, switch view to plain text mode