как использовать QGraphicsView :: RubberBandDrag? - PullRequest
2 голосов
/ 10 февраля 2020

Может ли кто-нибудь дать объяснение или, еще лучше, краткий пример, как использовать значение перечисления RubberBandDrag в QGraphicsView? PyQt5 был бы хорош, но я могу перевести с версии C ++, если это предпочтительнее для тех, кто может предоставить полезный пример.

NoDrag и ScrollHandDrag относительно легко понять (NoDrag делает мышь указатель, и вы можете захватывать щелчки в определенных местах, ScrollHandDrag делает мышь рукой, и вы можете реализовать щелчок и перетаскивание для прокрутки), но мне неясно, для чего можно использовать RubberBandDrag.

Прежде чем кто-то скажет "go прочитайте документы", вот предоставленная информация

https://doc.qt.io/qt-5/qgraphicsview.html

enum QGraphicsView :: DragMode

QGraphicsView :: RubberBandDrag

Появится резиновая полоса. Перетаскивание мыши установит геометрию резиновой ленты, и будут выбраны все элементы, покрытые резиновой лентой. Этот режим отключен для неинтерактивных представлений.

Это понятно, но я не уверен, как я мог бы на самом деле использовать RubberBandDrag. Есть ли способ использовать это для перетаскивания точек QPolygon вокруг после первоначального размещения? Это было бы действительно полезно.

1 Ответ

3 голосов
/ 10 февраля 2020

Флаг QGraphicsView::RubberBandDrag служит только для активации внутреннего QRubberBand:

enter image description here

А QRubberBand в целом предназначен только для визуализации выбранной области, и в случае QGraphicsView выберите элементы ниже этой области, если они доступны для выбора (включите флаг QGraphicsItem :: ItemIsSelectable).


В соответствии с вашим последний вопрос: Есть ли способ использовать это, чтобы перетаскивать точки QPolygon вокруг после первоначального размещения? Это было бы действительно полезно , мне кажется, что у вас есть проблема XY , поскольку кажется, что использование drag в терминологии заставляет вас думать, что она служит для перетаскивания элементы, потому что нет, это перетаскивание относится к способу создания резинкой.

Через несколько минут я покажу, как реализовать перетаскивание вершин для изменения QPolygon .

Ниже показано, как изменить положение вершин путем перетаскивания мыши:

import math

from PyQt5 import QtCore, QtGui, QtWidgets


class GripItem(QtWidgets.QGraphicsPathItem):
    circle = QtGui.QPainterPath()
    circle.addEllipse(QtCore.QRectF(-10, -10, 20, 20))
    square = QtGui.QPainterPath()
    square.addRect(QtCore.QRectF(-15, -15, 30, 30))

    def __init__(self, annotation_item, index):
        super(GripItem, self).__init__()
        self.m_annotation_item = annotation_item
        self.m_index = index

        self.setPath(GripItem.circle)
        self.setBrush(QtGui.QColor("green"))
        self.setPen(QtGui.QPen(QtGui.QColor("green"), 2))
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)
        self.setAcceptHoverEvents(True)
        self.setZValue(11)
        self.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))

    def hoverEnterEvent(self, event):
        self.setPath(GripItem.square)
        self.setBrush(QtGui.QColor("red"))
        super(GripItem, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self.setPath(GripItem.circle)
        self.setBrush(QtGui.QColor("green"))
        super(GripItem, self).hoverLeaveEvent(event)

    def mouseReleaseEvent(self, event):
        self.setSelected(False)
        super(GripItem, self).mouseReleaseEvent(event)

    def itemChange(self, change, value):
        if change == QtWidgets.QGraphicsItem.ItemPositionChange and self.isEnabled():
            self.m_annotation_item.movePoint(self.m_index, value)
        return super(GripItem, self).itemChange(change, value)


class PolygonAnnotation(QtWidgets.QGraphicsPolygonItem):
    def __init__(self, parent=None):
        super(PolygonAnnotation, self).__init__(parent)
        self.m_points = []
        self.setZValue(10)
        self.setPen(QtGui.QPen(QtGui.QColor("green"), 2))
        self.setAcceptHoverEvents(True)

        self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)

        self.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))

        self.m_items = []

    def addPoint(self, p):
        self.m_points.append(p)
        self.setPolygon(QtGui.QPolygonF(self.m_points))
        item = GripItem(self, len(self.m_points) - 1)
        self.scene().addItem(item)
        self.m_items.append(item)
        item.setPos(p)

    def movePoint(self, i, p):
        if 0 <= i < len(self.m_points):
            self.m_points[i] = self.mapFromScene(p)
            self.setPolygon(QtGui.QPolygonF(self.m_points))

    def move_item(self, index, pos):
        if 0 <= index < len(self.m_items):
            item = self.m_items[index]
            item.setEnabled(False)
            item.setPos(pos)
            item.setEnabled(True)

    def itemChange(self, change, value):
        if change == QtWidgets.QGraphicsItem.ItemPositionHasChanged:
            for i, point in enumerate(self.m_points):
                self.move_item(i, self.mapToScene(point))
        return super(PolygonAnnotation, self).itemChange(change, value)

    def hoverEnterEvent(self, event):
        self.setBrush(QtGui.QColor(255, 0, 0, 100))
        super(PolygonAnnotation, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
        super(PolygonAnnotation, self).hoverLeaveEvent(event)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    scene = QtWidgets.QGraphicsScene()
    w = QtWidgets.QGraphicsView(scene)

    polygon_item = PolygonAnnotation()
    scene.addItem(polygon_item)
    r = 100
    sides = 10

    for i in range(sides):
        angle = 2 * math.pi * i / sides
        x = r * math.cos(angle)
        y = r * math.sin(angle)
        p = QtCore.QPointF(x, y) + QtCore.QPointF(200, 200)
        polygon_item.addPoint(p)

    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
...