PyQt6: How can I fetch position of mouse pointer from QGraphicsScene and use the variables in the other class?

Question:

I’m new to pyqt6 and even to python. As the title indicates, I got stuck with handling mouse position variables. I was expecting to show coodinates of mouse pointer in the QLabel correspond to the mouse movement. I was able to fetch coordinates from mouseMoveEvent in the QGraphicsScene class to getPosition in the Window class. But, that coodinates couldn’t be passed to the other function in Window class.

Here is my code so far.

import sys
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QVBoxLayout, QWidget, QLabel

class GraphicsScene(QtWidgets.QGraphicsScene):
    def __init__(self, parent=None):
        super().__init__(parent)
    def mouseMoveEvent(self, event):
        self.posX = event.scenePos().x()
        Window.getPosition(Window, event.scenePos().x())

class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(GraphicsView, self).__init__(parent)
        self.setMouseTracking(True)
        scene = GraphicsScene(self)
        self.setScene(scene)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.Layout = QVBoxLayout() 
        self.gw = GraphicsView() # an image is meant to be set here.
        self.Layout.addWidget(self.gw)
        self.label = QLabel("Coordinate: x") # wanna show coorinates here correspond to the mouse movement. 
        self.Layout.addWidget(self.label)
        self.setLayout(self.Layout) 

    def getPosition(self, posX):
        self.label.setText("Coordinate: x" + str(self.posX))
        self.repaint()
        print(posX)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec())

and got an ERROR like this:

AttributeError: type object 'Window' has no attribute 'label'

It seemas the self in the getPosition function is set to GraphicsScene class after being called (unexpectedly for me). And I have no idea this approach works or not after reading several web documents and asking help for chatGPT. Possibly, I took wrong approach to layout of Widgets.

Any suggestion would be helpful because I’m stuck whole this week with dipression.

Thanks.

Asked By: nonoY

||

Answers:

Using class Window as parameter to setPosition was wrong, one needs to use an instance of this class. I did this by climbing up the parent() methods and there may be prettier ways to achieve the same. However, it works for now and I did not want to throw in too many changes.

I marked notable changes with comments.

#!/usr/bin/env python3

import sys
from PyQt6 import QtWidgets

class GraphicsScene(QtWidgets.QGraphicsScene):
    def __init__(self, parent=None):
        super().__init__(parent)

    def mouseMoveEvent(self, event):
        self.posX = event.scenePos().x()
        self.parent().parent().setPosition(event.scenePos().x()) # <-- crawl up the ancestry


class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(GraphicsView, self).__init__(parent)
        self.setMouseTracking(True)
        scene = GraphicsScene(self)
        self.setScene(scene)


class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.Layout = QtWidgets.QVBoxLayout()
        self.gw = GraphicsView(self) # <-- pass self here
        self.Layout.addWidget(self.gw)
        self.label = QtWidgets.QLabel("Coordinate: x") # wanna show coorinates here correspond to the mouse movement.
        self.Layout.addWidget(self.label)
        self.setLayout(self.Layout)

    def setPosition(self, posX): # <-- this is a setter, not a getter
        self.label.setText("Coordinate: x" + str(posX)) # <-- use argument posX
        self.repaint()
        print(posX)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec())
Answered By: Friedrich