Python Forum
QGraphicsObject at Mouse Position
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
QGraphicsObject at Mouse Position
#1
Hi, can anyone help with a MouseMoveEvent position to QGraphicsView mapping problem? I want to implement a Paint Brush, thus want to draw a circle around my mouse position and then paint that circle onto my GraphicsScene. Unfortunately I'am already struggling with the first step. The minimal example below shows the problem, setting the position of the MouseBrushObject in mouseMoveEvent of the View class results not in an expected behaviour. Playing with mapTo/From methods also doesn't work. Any comment helping me to find my mistakes is appreciated. Thanks

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):
        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(300, 300)
        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)


class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.viewer = Viewer(self)

        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_())
Reply
#2
try this

    def setPosition(self, pos):
        self._x = pos.x() - pos.x()/2
        self._y = pos.y() - pos.y()/2
        self.setPos(QPointF(self._x, self._y))
    def mouseMoveEvent(self, event):
        pos = event.pos()
        self._brushItem.setPosition(pos)
Reply
#3
Thank you Axel_Erfurt,

this is definitely close to what I want. Unfortunately this seems not to be the general solution. In my real code I also have implemented zooming, this and setting to fullscreen leads to an offset between the mouse and the circle again. Do you have another tip for me how to solve the problem for zooming or GraphicsView size changes?

Best regards

(Oct-27-2019, 02:36 PM)_meshman_ Wrote: Thank you Axel_Erfurt,

this is definitely close to what I want. Unfortunately this seems not to be the general solution. In my real code I also have implemented zooming, this and setting to fullscreen leads to an offset between the mouse and the circle again. Do you have another tip for me how to solve the problem for zooming or GraphicsView size changes?

Best regards

Ok found the solution, with the transform from Alex_Erfurt mapFromScene and mapToScene works. Many thank.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] QSlider jump to mouse click position MegasXLR 2 8,183 May-26-2018, 08:55 AM
Last Post: MegasXLR

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020