From what I understand you want to get the position on the window if you click anywhere in a widget.
To solve the problem, the logic is as follows:
- Get the mouse position with respect to the widget
- Convert that position to a global position, that is, with respect to the screen.
- Convert that global position to a position relative to the window.
For the first step if mousePressEvent()
is used, event.pos()
returns the position relative to the widget.
For the second step you must convert that position relative to the widget to global with mapToGlobal()
.
And for the third step mapFromGlobal()
of window is used.
def mousePressEvent(self, event):
p = event.pos() # relative to widget
gp = self.mapToGlobal(p) # relative to screen
rw = self.window().mapFromGlobal(gp) # relative to window
print("position relative to window: ", rw)
super(Widget, self).mousePressEvent(event)
Update:
The QGraphicsScene
is not a widget, it is not a visual element, although it is part of the representation of a visual element: the QGraphicsView
. For you to understand I will explain you with an analogy, let's say that there is a cameraman recording a scene, in that example the QGraphicsScene
is the scene and the QGraphicsView
is what the camera records, that is, it shows a piece of the QGraphicsScene
, so there could be another cameraman recording the scene from another point, so it would show the same scene from another perspective, so the position of the scene depends on the camera, so if your current question would be equivalent to saying which is the position of the point P respect to the camera i-th, and that from the scene is impossible, you should get it from the camera.
So in conclusion you should not use QGraphicsScene but QGraphicsView, the following solutions implement the same logic using 2 different methods:
1. Creating a custom class of QGraphicsView:
import sys
from PySide2 import QtGui, QtWidgets, QtCore
class GraphicsView(QtWidgets.QGraphicsView):
def mousePressEvent(self, event):
p = event.pos() # relative to widget
gp = self.mapToGlobal(p) # relative to screen
rw = self.window().mapFromGlobal(gp) # relative to window
print("position relative to window: ", rw)
super(GraphicsView, self).mousePressEvent(event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
scene = QtWidgets.QGraphicsScene(self)
view = GraphicsView(scene, self)
self.setCentralWidget(view)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.resize(500, 500)
main_window.show()
sys.exit(app.exec_())
2. Using eventfilter:
import sys
from PySide2 import QtGui, QtWidgets, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
scene = QtWidgets.QGraphicsScene(self)
self._view = QtWidgets.QGraphicsView(scene, self)
self.setCentralWidget(self._view)
self._view.installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self._view and event.type() == QtCore.QEvent.MouseButtonPress:
p = event.pos() # relative to widget
gp = self.mapToGlobal(p) # relative to screen
rw = self.window().mapFromGlobal(gp) # relative to window
print("position relative to window: ", rw)
return super(MainWindow, self).eventFilter(obj, event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.resize(500, 500)
main_window.show()
sys.exit(app.exec_())
On the other hand mapToGlobal()
is a method that must be called by an instance, when you use QtWidgets.QWidget.mapToGlobal()
there is no instance, my question is, what widget do you have the position? the position you have with respect to self, so you must use self.mapToGlobal()
, that works for the objects belonging to a class that inherit from QWidget
as QGraphicsView
, but not in QGraphicsScene
since it does not inherit from QWidget
, it is not a widget as indicated in the lines above.