如何使用python中Qt的“图形视图”框架?

2024-09-27 23:20:18 发布

您现在位置:Python中文网/ 问答频道 /正文

背景:我正在尝试使用Qt图形视图框架在python中制作一个VR演示,该框架允许定制呈现的gui。我可以选择包装Qt的两个不同的python模块:PyQt5和{}。不幸的是,这些模块中的每一个似乎都缺少图形视图框架中不同的关键要素。在

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。。。在

^{pr2}$

结果是ImportError: cannot import name 'QOpenGLPaintDevice'

我不确定是否有人成功地使用过python的Qt图形视图框架。如果没有,我想做第一个。在


Tags: 模块fromimport框架视图图形qtpyqt5
1条回答
网友
1楼 · 发布于 2024-09-27 23:20:18

在我看来,在PyQt5中没有启用qgraphicscenemouseevent并不是一个bug,而是在PySide2中启用的bug,因为如果您查看the docs就会发现qgraphicscenemouseevent没有公共构造函数。在

如果要在Qt图形框架中模拟鼠标移动,则必须将QMouseEvent发送到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_())

总之:

    >P>在Python中不能启用QLogGixStimeWouthEvor构造函数,因为它在C++中的Qt公共API中不可访问。所以PyQt5的行为是正确的,但是PySide2有一个bug。

  • PySide2没有实现QOpenGLPaintDevice类是一个可能的错误。

相关问题 更多 >

    热门问题