两个同步 QGrapchisView 层在缩放事件后错过对齐的场景矩形,但在平移事件后对齐

问题描述 投票:0回答:0

我有两类编辑过的

QGrapchicsView
,一类(
GraphicsView
)显示线条并启用缩放和平移。第二类 (
PolygonGrapchisView
) 仅根据从第一类接收到的信号更新场景矩形以匹配第一类
GraphicsView
的场景。平移事件由中间按钮触发

问题

PolygonGrapchisView
类接收来自
GraphicsView
类的信号并更新场景矩形以匹配两个类的范围。

无论位置或缩放级别如何,来自

mousePressEvent
类的
mouseReleaseEvent
mouseMoveEvent
GraphicsView
函数(平移事件)的信号都正确地设置了两个类的场景。我的意思是正确的,它在两个类中设置了矩形场景,以便在事件发生后,多边形和线相对于彼此保持在相同的位置。

当我尝试对

wheelEvent
(缩放事件)做同样的事情时,它有两种行为。第一个是当滚动条已满(占据整个水平和垂直条,没有移动滚动条的空间)或我们正在缩小时完成缩放事件,这里它“正确”工作。

第二个,是我们开始放大直到滚动条激活 并开始有移动空间,匹配场景矩形的信号失败。它没有对齐两个 graphicsview 类,这意味着多边形和线不会保持在相对于彼此的相同位置,而是开始重叠或彼此分开。如果您停止移动轮子并按下中间底部和平移场景,您可以解决这个未对齐问题。

这是情节的初始状态,这是所有鼠标事件后应该保持的状态。

这是在您放大直到激活滚动条时发生故障的地方。

预期行为

当我们在

PolygonGrapchisView
类中执行平移或缩放事件时,无论缩放级别或滚动条的位置如何,
GraphicsView
类的场景都会“正确”更新。它在鼠标事件期间和之后保持多边形和线之间的相对距离。

代码

from PyQt5 import QtWidgets, QtGui, QtCore
import sys


class PolygonGraphicsView(QtWidgets.QGraphicsView):

    def __init__(self, scene, parent=None):
        super(PolygonGraphicsView, self).__init__(scene, parent)
        # Set the anchor point for zooming and resizing
        self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)

        # Disable the scrollbars
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

    @QtCore.pyqtSlot(QtCore.QRectF, QtGui.QTransform)
    def setBounds(self, rect_scene, transform_matrix):
        #set scene rect
        self.setSceneRect(rect_scene)
        # Update the transformation matrix to match GraphicsView
        self.setTransform(transform_matrix)



class GraphicsView(QtWidgets.QGraphicsView):
    #señal para cambiar el viewport del qgrapichsview de los poligonos
    scene_rect_changed = QtCore.pyqtSignal(QtCore.QRectF, QtGui.QTransform)

    def __init__(self, scene, parent=None):
        super(GraphicsView, self).__init__(scene, parent)
        # recursivamente encontrar el qmainwindow
        cond = True
        self._parent = self.parentWidget()
        while cond:
            if isinstance(self._parent, QtWidgets.QMainWindow):
                cond = False
            else:
                self._parent = self._parent.parentWidget()

        # "variables iniciales"
        self.pos_init_class = None
        self.scale_factor = 1.5

        # # Set the anchor point for zooming and resizing
        self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)

        #señal para el qgrapichsview de poligonos
        self.polygon_graphicsview = self._parent.findChildren(PolygonGraphicsView, 'polygon_graphicsView')[0]
        self.scene_rect_changed.connect(self.polygon_graphicsview.setBounds)

        #apply transparent style sheet
        self.this_style_sheet = """ 
                background-color: transparent;
                selection-background-color:transparent;
            """
        self.setStyleSheet(self.this_style_sheet)
        self.viewport().setStyleSheet(self.this_style_sheet)

    def send_polygon_graphicsView_update(self):
        # Emit the scene_rect_changed signal with the transformation matrix
        new_rect = self.sceneRect()
        self.scene_rect_changed.emit(new_rect, self.transform())

    def mousePressEvent(self, event):
        pos = self.mapToScene(event.pos())
        # "pan mouse"
        if event.button() == QtCore.Qt.MiddleButton:
            self.pos_init_class = pos
            #update position
            self.send_polygon_graphicsView_update()
        else:
            super(GraphicsView, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        # pan
        if self.pos_init_class and event.button() == QtCore.Qt.MiddleButton:
            self.pos_init_class = None
            # update position
            self.send_polygon_graphicsView_update()
        else:
            super(GraphicsView, self).mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.pos_init_class:
            # "pan"
            delta = self.pos_init_class - self.mapToScene(event.pos())
            r = self.mapToScene(self.viewport().rect()).boundingRect()
            self.setSceneRect(r.translated(delta))
            # update position
            self.send_polygon_graphicsView_update()

        super(GraphicsView, self).mouseMoveEvent(event)

    def wheelEvent(self, event):
        old_pos = self.mapToScene(event.pos())

        # Determine the zoom factor
        if event.angleDelta().y() > 0:
            zoom_factor = self.scale_factor
        else:
            zoom_factor = 1 / self.scale_factor

        # Apply the transformation to the view
        transform = QtGui.QTransform()
        transform.translate(old_pos.x(), old_pos.y())
        transform.scale(zoom_factor, zoom_factor)
        transform.translate(-old_pos.x(), -old_pos.y())

        # Get the current transformation matrix and apply the new transformation to it
        current_transform = self.transform()
        self.setTransform(transform * current_transform)

        # update position
        self.send_polygon_graphicsView_update()

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # geometria de la ventana
        self.geometry = QtCore.QRect(0, 0, 800, 500)
        self.scene_rect_value = QtCore.QRectF(721200.96, -9679800.97, 500, -500)

        # central widget
        self.centralwidget = self.f_centralWidget()

        # polygon grapchisview widget
        self.polygon_graphicsView = self.f_polygon_grapchicsviewWidget(parent=self.centralwidget)

        # graphics view widget
        self.graphicsView, self.scene = self.f_graphicsviewWidget(parent=self.centralwidget)

        #dummy generator
        self.dummy_lines_polygons()
    ####################################################################################################################################################################################################
    # widget functions

    def f_centralWidget(self):
        # main window widget
        self.centralwidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralwidget)
        # define geometry main window
        self.setGeometry(self.geometry)
        return self.centralwidget

    def f_graphicsviewWidget(self, parent):
        # graphics view widget
        self.scene = QtWidgets.QGraphicsScene()
        self.graphicsView = GraphicsView(scene=self.scene, parent=parent)
        # geometry widget
        self.graphicsView.setGeometry(self.geometry)
        self.graphicsView.setSceneRect(self.scene_rect_value)
        return self.graphicsView, self.scene

    def f_polygon_grapchicsviewWidget(self, parent):
        # polygon graphics view widget
        self.polygon_scene = QtWidgets.QGraphicsScene()
        self.polygon_graphicsView = PolygonGraphicsView(scene=self.polygon_scene, parent=parent)
        self.polygon_graphicsView.setObjectName('polygon_graphicsView')
        # geometry widget
        self.polygon_graphicsView.setGeometry(self.geometry)
        self.polygon_graphicsView.setSceneRect(self.scene_rect_value)
        return self.polygon_graphicsView


    def dummy_lines_polygons(self):

        polygon_list = [[[721278.105, 9679978.402], [721378.918, 9679958.288], [721395.355, 9680058.781], [721294.491, 9680079.538]],
                        [[721398.840, 9679959.473], [721486.867, 9679930.441], [721502.381, 9680029.483], [721416.757, 9680055.152]]]
        for pol in polygon_list:
            polygon = QtGui.QPolygonF()
            for item in pol:
                x = item[0]
                y = -item[1]
                polygon.append(QtCore.QPointF(x, y))
            polygon_item = QtWidgets.QGraphicsPolygonItem(polygon)
            brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
            polygon_item.setBrush(brush)
            self.polygon_scene.addItem(polygon_item)

        # add some lines to the line view
        line_list = [[[721385.198, 9679948.971], [721404.402, 9680064.235] ], [[721404.402, 9680064.235], [721512.651, 9680035.611]]]
        pen = QtGui.QPen(QtGui.QColor(255, 0, 0))
        for line in line_list:
            x1 = line[0][0]
            y1 = -line[0][1]
            x2 = line[1][0]
            y2 = -line[1][1]
            line = QtWidgets.QGraphicsLineItem(x1, y1, x2, y2)
            line.setPen(pen)
            self.scene.addItem(line)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
python pyqt5 qt5 qgraphicsview
© www.soinside.com 2019 - 2024. All rights reserved.