Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python QGraphicsView.fitInView令人费解的行为_Python_Pyqt_Pyqt5_Qgraphicsview - Fatal编程技术网

Python QGraphicsView.fitInView令人费解的行为

Python QGraphicsView.fitInView令人费解的行为,python,pyqt,pyqt5,qgraphicsview,Python,Pyqt,Pyqt5,Qgraphicsview,我正在尝试制作一个带有两个QGraphicsView的小部件,以并排比较两个图像。当用户放大其中一个视图时,另一个视图应放大到同一区域。我的zoomIn函数发送一个带有可见场景矩形的信号,另一个视图中的一个插槽捕获该信号,并调用QGraphicsView.fitInView(矩形)使相同的图像区域可见。 令我惊讶的是,fitInView似乎将矩形(x,y,宽度,高度)视为(x,y,x+宽度,y+高度)。 这是一个错误还是我遗漏了什么 以下是我的代码示例: QGraphicsView子类 impo

我正在尝试制作一个带有两个QGraphicsView的小部件,以并排比较两个图像。当用户放大其中一个视图时,另一个视图应放大到同一区域。我的zoomIn函数发送一个带有可见场景矩形的信号,另一个视图中的一个插槽捕获该信号,并调用
QGraphicsView.fitInView(矩形)
使相同的图像区域可见。 令我惊讶的是,
fitInView
似乎将矩形(x,y,宽度,高度)视为(x,y,x+宽度,y+高度)。 这是一个错误还是我遗漏了什么

以下是我的代码示例:

QGraphicsView
子类

import logging
from PyQt5 import (
    QtWidgets as qw,
    QtCore as qc,
    QtGui as qg
)

class Display(qw.QGraphicsView):
    sigViewportAreaChanged = qc.pyqtSignal(qc.QRectF)

    def __init__(self, *args, **kwargs):
        super(Display, self).__init__(*args, **kwargs)
        ...
        self.zoomInAction = qw.QAction('Zoom in')
        self.zoomInAction.triggered.connect(self.zoomIn)

    @qc.pyqtSlot()
    def zoomIn(self):
        self.scale(1.2, 1.2)
        pos = self.viewport().pos()
        size = self.viewport().size()
        logging.debug(f'{self.objectName()}: viewport:: pos: {pos}, size: {size}')
        pos = self.mapToScene(pos)
        size = self.mapToScene(size.width(), size.height())
        logging.debug(f'{self.objectName()}: scene:: pos: {pos}, size: {size}')
        view_area = qc.QRectF(pos.x(), pos.y(), size.x(), size.y())
        logging.debug(
            f'Emitting changed viewport area, {view_area},\n{mat}')
        self.sigViewportAreaChanged.emit(view_area)

    def setViewportRect(self, rect: qc.QRectF) -> None:
        logging.debug(f'{self.objectName()} <- {self.sender().objectName()}\nFit view to {rect}')
        pos = self.viewport().pos()
        size = self.viewport().size()
        logging.debug(f'{self.objectName()}: before fitting area: viewport:: pos: {pos}, size: {size}')
        pos = self.mapToScene(pos)
        size = self.mapToScene(size.width(), size.height())
        logging.debug(f'{self.objectName()}: before fitting area: scene:: pos: {pos}, size: {size}')
        # self.fitInView(rect)  # Incorrectly sets the visible area
        self.fitInView(rect.x(), rect.y(), rect.width() - rect.x(), rect.height() - rect.y())  # this works
        pos = self.viewport().pos()
        size = self.viewport().size()
        logging.debug(f'{self.objectName()}: after fitting area: viewport:: pos: {pos}, size: {size}')
        pos = self.mapToScene(pos)
        size = self.mapToScene(size.width(), size.height())
        logging.debug(f'{self.objectName()}: after fitting area: scene:: pos: {pos}, size: {size}')  # this suggests that the new viewport is (x, y, x+width, y+height) instead of (x, y, width, height)

我相信你计算尺寸的方法是错误的。您应该相对于
pos
的转换值来计算它。由于您知道宽度和高度的值,因此可以根据
pos
的场景值计算
view\u area
的右下角

viewport\u pos=self.viewport().pos()
场景位置=自映射场景(视口位置)
宽度=self.viewport().size().width()
高度=self.viewport().size().height()
右下角=QPointF(宽度-场景位置x(),高度()-场景位置y())

在没有减法的情况下,你假设
视图区域的原点位于
(0,0)
,而事实上它是
位置

好的,在阅读了@Roney Gomes的答案后,我发现了我的错误

为了将大小缩放到场景坐标系,我将大小作为点传递到
mapToScene

但点和大小在概念上是不同的,虽然大小不依赖于坐标系的原点,但点却依赖于坐标系的原点。
mapToScene
将其参数视为一个点,将其转换以反映新的坐标系

因此,我需要减去新坐标系的原点,它实际上是视口的左上角,以恢复大小

更简单的解决方案是直接映射视口矩形:

rect = self.mapToScene(self.viewport().rect())  
rect = rect.boundingRect() # mapToScene(rect) returns QPolygonF
self.sigViewportAreaChanged.emit(rect)

我认为宽度和高度应该独立于原点,因为它们测量空间中的间隔(即,线的长度不应根据坐标系的原点而改变)。现在我了解到尺寸上的
mapToScene
将其视为一个点,并将其转换为坐标变化。
rect = self.mapToScene(self.viewport().rect())  
rect = rect.boundingRect() # mapToScene(rect) returns QPolygonF
self.sigViewportAreaChanged.emit(rect)