Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Drawing QGraphicsObject at Mouse Position

Drawing QGraphicsObject at Mouse Position

Scheduled Pinned Locked Moved Unsolved Qt for Python
3 Posts 2 Posters 2.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    patrice079
    wrote on last edited by
    #1

    Dear Experts, I'am struggling with mouse position mapping to a QGraphicsScene and any help is highly appreciated.

    I've a custom QGraphicsScene class with a mouseMoveEvent emiting my mouse position like so:

    class MyScene(QGraphicsScene):
        """
        This is a custom QGraphicsScene implementation.
        """
        hoverOnSceneSignal = QtCore.pyqtSignal(QPointF)
        
        ....
        
        def mouseMoveEvent(self, event):
            self.hoverOnSceneSignal.emit(event.scenePos())
            super(MyScene, self).mouseMoveEvent(event)
    

    Then I have a custom Widget drawing and image on a custom QGraphicsView with MyScene attached. This widget listens to the signal hoverOnSceneSignal:

    class Viewer(QWidget):
        def __init__(self, parent=None):
            super(Viewer, self).__init__(parent=parent)
            self.myscene = MyScene(self)
            self.myview = MyView(self)
            self.myview.setScene(self.myscene)
            self._mousebrush = MouseBrushItem()
    
        def enterEvent(self, event):
            self.myscene.addItem(self._mousebrush)
            return super(Viewer, self).enterEvent(event)
    
        @QtCore.pyqtSlot(QPointF)
        def onHoverTriggered(self, pos):
            self._mousebrush.setPosition(pos)
    

    _mousebrush is a custom QGraphicsObject added on MyScene painting an ellipse. The goal is to draw an ellipse at my mouse position, which should result in a photoshop like brush.

    class MouseBrushItem(QGraphicsObject):
        def __init__(self):
            super(MouseBrushItem, self).__init__()
            self._size = 1
            self._x = 0
            self._y = 0
            self._color = None
            self._pen = None
            self._brush = None
            self.setColor(QColor(255, 255, 255, 255))
    
        def paint(self, painter, option, widget):
            rect = self.boundingRect()
            painter.setPen(self._pen)
            painter.setBrush(self._brush)
            painter.drawEllipse(rect)
    
        def boundingRect(self):
            return QRectF(self._x, self._y, self._size, self._size)
    
        def setColor(self, color):
            self._color = color
            self._pen = QPen(self._color, 1)
            self._brush = QBrush(QColor(self._color.red(), self._color.green(), self._color.blue(), 40))
    
        def setSize(self, size):
            self._size = size
    
        def setPosition(self, pos):
            self._x = pos.x()
            self._y = pos.y()
            self.setPos(pos)
    

    Unfortunately I'am not able to draw the circle sticked to my mouse. Everything works so far but the ellipse is running away from my mouse. I tried to play with mapFromWorld, mapToWorld, mapFromScene, mapToScene with no success. Seem I misunderstand anything important. Would be really thankful for comments helping me to draw a circle at my mouse if it moves on my QGraphicsScene.

    Many Thanks and best regards

    1 Reply Last reply
    0
    • P Offline
      P Offline
      patrice079
      wrote on last edited by
      #2

      @Denni-0 Many Thanks for your good advices, I will take the time reading more about super. To be honest, I saw it in examples and consequently copied it expecting that it is the modern version of QWidget.init(self, parent=parent). I will also try to extract my problem to make the code small enough to post . Thought what I posted might be enough to see where my errors are.

      1 Reply Last reply
      0
      • P Offline
        P Offline
        patrice079
        wrote on last edited by
        #3

        @Denni-0 Here is a minimal code example, the question is how do I correctly draw the circle at the mouse position and get the coodinates on my pixmap for drawing? Can anyone help me with this issue?

        import sys
        from PyQt5.QtCore import Qt, QRectF, QPointF
        from PyQt5.QtGui import QPixmap, QTransform, QBrush, QColor, QPen
        from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QSizePolicy, QSpacerItem, QGraphicsObject
        
        
        class MouseBrushObject(QGraphicsObject):
            def __init__(self):
                QGraphicsObject.__init__(self)
                self._size = 10
                self._x = 0
                self._y = 0
                self._pen = None
                self._brush = None
                self._color = None
                self.setColor(QColor(255, 0, 0, 255))
        
            def paint(self, painter, option, widget):
                rect = self.boundingRect()
                painter.setPen(self._pen)
                painter.setBrush(self._brush)
                painter.drawEllipse(rect)
        
            def boundingRect(self):
                return QRectF(self._x, self._y, self._size, self._size)
        
            def setColor(self, color):
                self._color = color
                self._pen = QPen(self._color, 1)
                self._brush = QBrush(QColor(self._color.red(), self._color.green(), self._color.blue(), 40))
        
            def setSize(self, size):
                self._size = size
        
            def setPosition(self, pos):
                print(f"brush pos: {pos.x()}, {pos.y()}")
                self._x = pos.x()-self._size/2
                self._y = pos.y()-self._size/2
                self.setPos(QPointF(self._x, self._y))
        
        
        class View(QGraphicsView):
            def __init__(self, parent=None):
                QGraphicsView.__init__(self, parent=parent)
                self.setMouseTracking(True)
                self.scene = QGraphicsScene(self)
                self.setScene(self.scene)
                pixmap = QPixmap(800, 440)
                self.scene.addItem(QGraphicsPixmapItem(pixmap))
                self.setTransform(QTransform().scale(1, 1).rotate(0))
                self.scene.setBackgroundBrush(QBrush(Qt.lightGray))
                self._brushItem = MouseBrushObject()
        
            def mouseMoveEvent(self, event):
                pos = event.pos()
                #pos = self.mapToScene(pos)
                #pos = self.mapFromScene(pos)
                #pos = self.mapToGlobal(pos)
                #pos = self.mapFromGlobal(self.mapToGlobal(pos))
                #pos = self.mapToGlobal(self.mapFromGlobal(pos))
                #pos = self.mapToGlobal(self.mapFromScene(pos))
                self._brushItem.setPosition(pos)
        
            def enterEvent(self, event):
                self.scene.addItem(self._brushItem)
                return super(View, self).enterEvent(event)
        
            def leaveEvent(self, event):
                self.scene.removeItem(self._brushItem)
                return super(View, self).leaveEvent(event)
        
        
        class Viewer(QWidget):
            def __init__(self, parent=None):
                QWidget.__init__(self, parent=parent)
        
                layout = QVBoxLayout()
                self.view = View(self)
                self.setLayout(layout)
        
                layout.addWidget(self.view)
                layout.addStretch(1)
        
        
        class MainWindow(QMainWindow):
        
            def __init__(self):
                QMainWindow.__init__(self)
                self.viewer = Viewer(self)
                self.viewer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
                layout = QVBoxLayout()
                layout.addWidget(self.viewer)
                centralwidget = QWidget(self)
                centralwidget.setLayout(layout)
                self.setCentralWidget(centralwidget)
        
        
        if __name__ == '__main__':
            app = QApplication(sys.argv)
            main = MainWindow()
            main.show()
            sys.exit(app.exec_())
        
        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved