Распространение событий QGraphicsSvgItem (Интерактивный просмотрщик svg) - PullRequest
0 голосов
/ 13 ноября 2018

В настоящее время я создаю минималистичный просмотрщик svg, в котором пользователь должен иметь возможность выбирать подэлементы нарисованной графики.

Кусочный рендеринг SVG достигается с помощью

QGraphicsSvgItem с общим рендерером. Затем элементы добавляются один за другим в QGraphicsScene, который связан с QGraphicsView.

Нет, самое сложное. Мне нужен одиночный выбор предметов (нажав на них) и множественный выбор с резинкой.

В настоящее время я борюсь с распространением событий щелчка мыши. В документации сказано, что все события распространяются от детей к родителям. Другими словами: щелкнув элемент SvgItem, я бы предположил, что обработчик события Item запускается до обработчика средства просмотра. Это не тот случай.

Я создал пример приложения:

from PyQt5 import QtWidgets
from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer


class SvgItem(QGraphicsSvgItem):
    def __init__(self, id, renderer, parent=None):
        super().__init__(parent)
        self.id = id
        self.setSharedRenderer(renderer)
        self.setElementId(id)
        bounds = renderer.boundsOnElement(id)
        self.setPos(bounds.topLeft())
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)

    def mousePressEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('svg item: ' + self.id + ' - mousePressEvent()')
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('svg item: ' + self.id + ' - mouseReleaseEvent()')
        super().mouseReleaseEvent(event)


class SvgViewer(QtWidgets.QGraphicsView):
    def __init__(self, parent):
        super().__init__(parent)
        self._scene = QtWidgets.QGraphicsScene(self)
        self._renderer = QSvgRenderer()
        self.setScene(self._scene)

    def set_svg(self, data):
        self.resetTransform()
        self._scene.clear()
        self._renderer.load(data)

        item1 = SvgItem('p2', self._renderer)
        self._scene.addItem(item1)

        item2 = SvgItem('p3', self._renderer)
        self._scene.addItem(item2)

    def mousePressEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('SvgViewer - mousePressEvent()')
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'):
        print('SvgViewer - mouseReleaseEvent()')
        super().mouseReleaseEvent(event)


class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.viewer = SvgViewer(self)
        vb_layout = QtWidgets.QVBoxLayout(self)
        vb_layout.addWidget(self.viewer)

        img = b'''
                <svg viewBox='0 0 108 95' xmlns='http://www.w3.org/2000/svg'>
                    <g transform='scale(0.1)'>
                        <path id="p2" d='M249,699v43h211v-43h-64l-2,3l-2,4l-4,3c0,0-1,2-2,2h-4c-2,0-3,0-4,1c-1,1-3,1-3,
                            2l-3,4c0,1-1,2-2,2h-4c0,0-2,1-3,0l-3-1c-1,0-3-1-3-2c-1-1,0-2-1-3l-1-3c-1-1-2-1-3-1c-1,0-4,
                            0-4-1c0-2,0-3-1-4v-3v-3z'/>
                        <path id="p3" d='M385,593c0,9-6,15-13,15c-7,0-13-6-13-15c0-8,12-39,14-39c1,0,12,31,12,39'/>
                    </g>
                </svg>'''
        self.viewer.set_svg(img)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 600, 400)
    window.show()
    sys.exit(app.exec_())

Щелчок по отображаемому элементу svg приводит к следующему выводу консоли:

SvgViewer - mousePressEvent()
svg item: p3 - mousePressEvent()
SvgViewer - mouseReleaseEvent()
svg item: p3 - mouseReleaseEvent()

Моя цель - следующее поведение:

  1. пользователь нажимает на элемент -> этот элемент выбран (событие принято, а прямоугольник выбора не создан)
  2. пользователи нажимают на пустую область и начинают двигать мышь -> начинает появляться прямоугольник выбора

Как я могу пропустить обработку событий в средстве просмотра, когда щелчок левой кнопкой мыши находится над видимым элементом (предпочтительно без какой-либо логики, основанной на проверках положения вручную) *

Любое предложение приветствуется!

...