Как мне использовать каркас Qt "Graphics View" из python? - PullRequest
0 голосов
/ 09 июля 2019

Справочная информация: я пытаюсь сделать демонстрацию виртуальной реальности в Python, используя каркас Qt Graphics View, который позволяет настраивать пользовательские графические интерфейсы. У меня есть опция двух разных модулей Python, которые обертывают Qt: PyQt5 и 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-binding 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'

Я не уверен, что кто-нибудь когда-либо успешно использовал каркас Qt Graphics View из python. Если нет, я бы хотел быть первым.

1 Ответ

0 голосов
/ 09 июля 2019

Мне кажется, что это не ошибка, что QGraphicsSceneMouseEvent не включен в PyQt5, но это ошибка, которая включена в 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_())

В заключение:

  • Конструктор QGraphicsSceneMouseEvent не должен быть включен в python, посколькуон не доступен в общедоступном API Qt в C ++.Таким образом, поведение PyQt5 является правильным, но PySide2 имеет ошибку.

  • То, что PySide2 не имеет реализованного класса QOpenGLPaintDevice, является возможной ошибкой.

...