Pyside2如何获取鼠标位置?
Pyside2 how to get mouse position?
我想在我的 pyside2 应用程序中获取鼠标位置。(不是 QCursor 提供的桌面鼠标位置)我尝试了两种方法。下面是我的代码。
import sys
from PySide2 import QtGui, QtWidgets, QtCore
class Palette(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
def mousePressEvent(self, event):
print(event.pos()) # always return (0,0)
print(QtWidgets.QWidget.mapToGlobal(QtCore.QPoint(0, 0))) #makes parameter type error
print(QtWidgets.QWidget.mapToGlobal(QtWidgets.QWidget)) # makes parameter type error
print(QtWidgets.QWidget.mapToGlobal(QtWidgets.QWidget.pos())) # makes parameter type error
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
palette = Palette(self)
view = QtWidgets.QGraphicsView(palette, self)
view.resize(500, 500)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.resize(500, 500)
main_window.show()
app.exec_()
我很想知道如何获得我的鼠标位置...
据我了解,如果您单击小部件中的任意位置,您想获得 window 上的位置。
解决问题,逻辑如下:
- 获取鼠标相对于小部件的位置
- 将该位置转换为全局位置,即相对于屏幕的位置。
- 将该全局位置转换为相对于 window 的位置。
对于第一步,如果使用 mousePressEvent()
,event.pos()
returns 相对于小部件的位置。
对于第二步,您必须使用 mapToGlobal()
将相对于小部件的位置转换为全局位置。
第三步使用 window 的 mapFromGlobal()
。
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)
更新:
QGraphicsScene
不是小部件,它不是视觉元素,尽管它是视觉元素表示的一部分:QGraphicsView
。为了方便大家理解我打个比方给大家解释一下,假设有一个摄像师在录制一个场景,在那个例子中QGraphicsScene
是场景,QGraphicsView
是摄像机录制的内容,也就是, 它显示了 QGraphicsScene
的一部分,所以可能有另一个摄影师从另一个点拍摄场景,所以它会从另一个角度显示相同的场景,所以场景的位置取决于相机,所以如果你现在的问题相当于说点P相对于第i个相机的位置是哪个,从场景中是不可能的,你应该从相机中得到它。
所以总而言之,您不应该使用 QGraphicsScene,而应该使用 QGraphicsView,以下解决方案使用 2 种不同的方法实现相同的逻辑:
1.创建 QGraphicsView 的自定义 class:
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。使用事件过滤器:
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_())
另一方面,mapToGlobal()
是一个必须由实例调用的方法,当您使用 QtWidgets.QWidget.mapToGlobal()
时没有实例,我的问题是,您的位置是什么小部件?你相对于自己的位置,所以你必须使用 self.mapToGlobal()
,它适用于属于 class 的对象,它继承自 QWidget
作为 QGraphicsView
,但不适用于QGraphicsScene
因为它不是从 QWidget
继承的,所以它不是上面几行中指出的小部件。
我最近发现了一种更通用的获取光标位置的方法,如果您不想通过子类化和事件的话。
# get cursor position
cursor_position = QtGui.QCursor.pos()
print cursor_position
### Returns PySide2.QtCore.QPoint(3289, 296)
我想在我的 pyside2 应用程序中获取鼠标位置。(不是 QCursor 提供的桌面鼠标位置)我尝试了两种方法。下面是我的代码。
import sys
from PySide2 import QtGui, QtWidgets, QtCore
class Palette(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
def mousePressEvent(self, event):
print(event.pos()) # always return (0,0)
print(QtWidgets.QWidget.mapToGlobal(QtCore.QPoint(0, 0))) #makes parameter type error
print(QtWidgets.QWidget.mapToGlobal(QtWidgets.QWidget)) # makes parameter type error
print(QtWidgets.QWidget.mapToGlobal(QtWidgets.QWidget.pos())) # makes parameter type error
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
palette = Palette(self)
view = QtWidgets.QGraphicsView(palette, self)
view.resize(500, 500)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.resize(500, 500)
main_window.show()
app.exec_()
我很想知道如何获得我的鼠标位置...
据我了解,如果您单击小部件中的任意位置,您想获得 window 上的位置。
解决问题,逻辑如下:
- 获取鼠标相对于小部件的位置
- 将该位置转换为全局位置,即相对于屏幕的位置。
- 将该全局位置转换为相对于 window 的位置。
对于第一步,如果使用 mousePressEvent()
,event.pos()
returns 相对于小部件的位置。
对于第二步,您必须使用 mapToGlobal()
将相对于小部件的位置转换为全局位置。
第三步使用 window 的 mapFromGlobal()
。
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)
更新:
QGraphicsScene
不是小部件,它不是视觉元素,尽管它是视觉元素表示的一部分:QGraphicsView
。为了方便大家理解我打个比方给大家解释一下,假设有一个摄像师在录制一个场景,在那个例子中QGraphicsScene
是场景,QGraphicsView
是摄像机录制的内容,也就是, 它显示了 QGraphicsScene
的一部分,所以可能有另一个摄影师从另一个点拍摄场景,所以它会从另一个角度显示相同的场景,所以场景的位置取决于相机,所以如果你现在的问题相当于说点P相对于第i个相机的位置是哪个,从场景中是不可能的,你应该从相机中得到它。
所以总而言之,您不应该使用 QGraphicsScene,而应该使用 QGraphicsView,以下解决方案使用 2 种不同的方法实现相同的逻辑:
1.创建 QGraphicsView 的自定义 class:
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。使用事件过滤器:
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_())
另一方面,mapToGlobal()
是一个必须由实例调用的方法,当您使用 QtWidgets.QWidget.mapToGlobal()
时没有实例,我的问题是,您的位置是什么小部件?你相对于自己的位置,所以你必须使用 self.mapToGlobal()
,它适用于属于 class 的对象,它继承自 QWidget
作为 QGraphicsView
,但不适用于QGraphicsScene
因为它不是从 QWidget
继承的,所以它不是上面几行中指出的小部件。
我最近发现了一种更通用的获取光标位置的方法,如果您不想通过子类化和事件的话。
# get cursor position
cursor_position = QtGui.QCursor.pos()
print cursor_position
### Returns PySide2.QtCore.QPoint(3289, 296)