背景:我正在尝试使用Qt Graphics View框架在python中制作VR演示,该框架允许自定义呈现的GUI。我可以选择包装Qt:PyQt5和的两个不同的python模块PySide2。不幸的是,这些模块中的每个模块似乎都在Graphics View Framework中缺少不同的关键要素。
PyQt5似乎缺少的构造函数QGraphicsSceneMouseEvent,这是从VR控制器手势创建合成鼠标事件所需的。这个简短的PyQt5程序...
from PyQt5.QtCore import QEvent, QPointF, Qt
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QGraphicsSceneMouseEvent
from PyQt5.QtGui import QOpenGLPaintDevice # No problem for PyQt5
pos = QPointF(20, 20)
event1 = QMouseEvent(QEvent.MouseMove, pos, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
device = QOpenGLPaintDevice(100, 100)
# Problem: TypeError: PyQt5.QtWidgets.QGraphicsSceneMouseEvent cannot be instantiated or sub-classed
event2 = QGraphicsSceneMouseEvent(QEvent.GraphicsSceneMouseMove)
...结果是 TypeError: PyQt5.QtWidgets.QGraphicsSceneMouseEvent cannot be instantiated or sub-classed
看来,好消息是,替代的Qt绑定PySide2模块可以构建一个QGraphicsSceneMouseEvent没有抱怨的对象。但是PySide2缺少QOpenGLPaintDevice类,我实际上需要绘制它。这个非常相似的程序,它使用PySide2 ...
from PySide2.QtCore import QEvent, QPointF, Qt
from PySide2.QtGui import QMouseEvent
from PySide2.QtWidgets import QGraphicsSceneMouseEvent
pos = QPointF(20, 20)
event1 = QMouseEvent(QEvent.MouseMove, pos, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
event2 = QGraphicsSceneMouseEvent(QEvent.GraphicsSceneMouseMove) # No Problem for PySide2
from PySide2.QtGui import QOpenGLPaintDevice # Problem: PySide2 does not have this class
device = QOpenGLPaintDevice(100, 100)
结果是 ImportError: cannot import name 'QOpenGLPaintDevice'
我不确定谁能成功使用python的Qt Graphics View框架。如果没有,我想成为第一个。
在我看来,在PyQt5中未启用QGraphicsSceneMouseEvent并不是一个错误,但是在PySide2中已启用了一个错误,因为如果您查看文档,就会发现QGraphicsSceneMouseEvent没有公共构造函数。
如果要在Qt Graphics Framework中模拟鼠标移动,则必须将QMouseEvent发送到viewport()QGraphicsView的。
在下面的示例中,我演示了如何使用QMouseEvent模拟鼠标来移动项目:
from functools import partial
from PySide2 import QtCore, QtGui, QtWidgets
# from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.m_scene = QtWidgets.QGraphicsScene(QtCore.QRectF(0, 0, 400, 400), self)
self.m_graphicsview = QtWidgets.QGraphicsView(self.m_scene)
self.setCentralWidget(self.m_graphicsview)
self.resize(640, 480)
self.m_item = QtWidgets.QGraphicsRectItem(QtCore.QRectF(-50, -50, 100, 100))
self.m_item.setFlags(
self.m_item.flags() | QtWidgets.QGraphicsItem.ItemIsMovable
)
self.m_item.setBrush(QtGui.QColor("salmon"))
self.m_item.setPos(100, 100)
self.m_scene.addItem(self.m_item)
QtCore.QTimer.singleShot(1000, self.emulate_move_item)
def emulate_move_item(self):
sp = self.m_item.mapToScene(self.m_item.boundingRect().center())
lp = self.m_graphicsview.mapFromScene(sp)
end_pos = lp + QtCore.QPoint(100, 100)
self.press(lp)
animation = QtCore.QVariantAnimation(
self,
startValue=lp,
endValue=end_pos
)
animation.valueChanged.connect(self.moveTo)
animation.finished.connect(partial(self.release, end_pos))
animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
def press(self, pos):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseButtonPress,
pos,
self.m_graphicsview.mapToGlobal(pos),
QtCore.Qt.LeftButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.postEvent(self.m_graphicsview.viewport(), event)
def moveTo(self, pos):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseMove,
pos,
self.m_graphicsview.viewport().mapToGlobal(pos),
QtCore.Qt.LeftButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.postEvent(self.m_graphicsview.viewport(), event)
def release(self, pos):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseButtonRelease,
pos,
self.m_graphicsview.viewport().mapToGlobal(pos),
QtCore.Qt.LeftButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.postEvent(self.m_graphicsview.viewport(), event)
def double_click(self, pos):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseButtonDblClick,
pos,
self.m_graphicsview.viewport().mapToGlobal(pos),
QtCore.Qt.LeftButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.postEvent(self.m_graphicsview.viewport(), event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
结论:
不能在python中启用QGraphicsSceneMouseEvent构造函数,因为在C ++中的Qt的公共API中无法访问它。因此PyQt5的行为是正确的,但是PySide2有一个错误。
PySide2没有实现QOpenGLPaintDevice类是一个可能的错误。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。