如何同时控制两个加载不同内容的QGraphicsView实现同步缩放平移
实现思路
- 给两个
QGraphicsView分别绑定独立的QGraphicsScene,各自添加不同的QGraphicsPixmapItem加载不同图片,解决同场景只能显示相同内容的问题 - 关闭item的可移动属性,改为通过操作视图的视口实现平移,将其中一个视图的滚动条信号、缩放参数实时同步到另一个视图,实现操作完全同步
调整后的核心代码
可直接复用你现有的UI代码,主窗口逻辑修改如下:
import sys from PyQt5 import QtWidgets from PyQt5.QtCore import QRectF, Qt from PyQt5.QtGui import QPixmap, QPainter, QColor from PyQt5.QtWidgets import QGraphicsPixmapItem, QMainWindow, QGraphicsScene from ui.preview_test import Ui_MainWindow class mainwindow(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self._delta = 0.1 self._is_dragging = False self._last_mouse_pos = None # 视图基础配置统一设置 for view in [self.graphicsView_1, self.graphicsView_2]: view.setCursor(Qt.OpenHandCursor) view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform) view.setBackgroundBrush(Qt.black) # 禁用视图自带的拖拽滚动,自定义实现同步逻辑 view.setDragMode(QtWidgets.QGraphicsView.NoDrag) # 初始化两个独立场景 self._scene1 = QGraphicsScene(self) self._scene2 = QGraphicsScene(self) self.graphicsView_1.setScene(self._scene1) self.graphicsView_2.setScene(self._scene2) # 分别加载不同图片,替换为你自己的图片路径即可 self._item1 = QGraphicsPixmapItem() self._item1.setPixmap(QPixmap("第一张图片路径")) self._scene1.addItem(self._item1) self._item2 = QGraphicsPixmapItem() self._item2.setPixmap(QPixmap("第二张图片路径")) self._scene2.addItem(self._item2) # 双向绑定滚动条信号,任意一个视图平移都会同步到另一个 self.graphicsView_1.horizontalScrollBar().valueChanged.connect( lambda val: self.graphicsView_2.horizontalScrollBar().setValue(val) ) self.graphicsView_1.verticalScrollBar().valueChanged.connect( lambda val: self.graphicsView_2.verticalScrollBar().setValue(val) ) self.graphicsView_2.horizontalScrollBar().valueChanged.connect( lambda val: self.graphicsView_1.horizontalScrollBar().setValue(val) ) self.graphicsView_2.verticalScrollBar().valueChanged.connect( lambda val: self.graphicsView_1.verticalScrollBar().setValue(val) ) self.show() def setBackground(self, color): if isinstance(color, QColor): brush = color elif isinstance(color, (str, Qt.GlobalColor)): color = QColor(color) brush = color if color.isValid() else Qt.black else: brush = Qt.black self.graphicsView_1.setBackgroundBrush(brush) self.graphicsView_2.setBackgroundBrush(brush) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: # 仅当鼠标落在两个视图区域内时激活拖拽逻辑 pos = event.pos() if self.graphicsView_1.geometry().contains(pos) or self.graphicsView_2.geometry().contains(pos): self._is_dragging = True self._last_mouse_pos = event.pos() self.setCursor(Qt.ClosedHandCursor) super().mousePressEvent(event) def mouseMoveEvent(self, event): if self._is_dragging and self._last_mouse_pos is not None: # 计算鼠标偏移量,同步平移两个视图 offset = event.pos() - self._last_mouse_pos for view in [self.graphicsView_1, self.graphicsView_2]: view.horizontalScrollBar().setValue(view.horizontalScrollBar().value() - offset.x()) view.verticalScrollBar().setValue(view.verticalScrollBar().value() - offset.y()) self._last_mouse_pos = event.pos() super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self._is_dragging = False self._last_mouse_pos = None self.setCursor(Qt.OpenHandCursor) super().mouseReleaseEvent(event) def wheelEvent(self, event): if event.angleDelta().y() > 0: self.zoom(1 + self._delta) else: self.zoom(1 - self._delta) event.accept() def zoom(self, factor): # 统一用第一个视图的缩放系数做边界判断,避免两个视图比例不一致 current_factor = self.graphicsView_1.transform().scale(factor, factor).mapRect(QRectF(0, 0, 1, 1)).width() if current_factor < 0.07 or current_factor > 100: return # 同时给两个视图应用缩放 for view in [self.graphicsView_1, self.graphicsView_2]: view.scale(factor, factor) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) window = mainwindow() app.exec_()
实现说明
- 两个场景独立互不干扰,可分别加载不同图片、添加不同的图形元素
- 滚动条信号双向绑定,无论操作哪个视图,另一个都会同步平移
- 缩放操作同时作用于两个视图,统一用同一个基准值判断缩放边界,避免出现两个视图缩放比例不一致的问题
- 拖拽逻辑直接操作视图滚动条,不需要依赖item的可移动属性,适配任意场景内容的同步
内容的提问来源于stack exchange,提问作者KimJitae
相关产品推荐
相关产品推荐

