如何解决使用 QGraphicsView 场景放大鼠标位置
我想让用户在 QGraphicView 的场景中放大图像,允许他放大鼠标位置。
我尝试通过多种方式实现这种缩放,但不幸的是,我无法按需要使其工作。
如果通过 QGraphicspixmapItem 的 setScale 和 setTransformOriginpoint 实现这一点,只要用户不移动鼠标在放大图像上的位置,该解决方案就可以正常工作,如果他这样做了 - 显示的缩放图像是不正确的。请在下面找到一个最低限度的可重现示例:
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication,QLabel,QMainWindow,QGraphicsView,QGraphicspixmapItem,QGraphicsScene,QPushButton,QWidget,QVBoxLayout,QShortcut
from PyQt5.QtCore import Qt
from PyQt5 import QtCore,QtGui
from PyQt5.QtGui import QKeySequence,QShortcutEvent,QCursor
global qpixmap
global lvlofzoom
lvlofzoom =1
class MainWindow(QMainWindow):
def __init__(self,*args,**kwargs):
super(MainWindow,self).__init__(*args,**kwargs)
self.setFixedSize(1200,800)
self.Imagedisplay = QGraphicsView()
self.qwidget = QWidget()
self.Zoom_inBtn = QPushButton("Zoom in (CTRL + F)")
self.Zoom_outBtn = QPushButton("Zoom out (CTRL + G)")
self.setimgBtn = QPushButton("Load Image (CTRL+P)")
self.Zoom_inBtn.clicked.connect(lambda: self.zoomin())
self.Zoom_outBtn.clicked.connect(lambda: self.zoomout())
self.setimgBtn.clicked.connect(lambda:self.loadimg())
self.Zoom_inBtn.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F))
self.Zoom_outBtn.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_G))
self.setimgBtn.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_P))
self.vlayout = QVBoxLayout()
self.vlayout.addWidget(self.Imagedisplay)
self.vlayout.addWidget(self.setimgBtn)
self.vlayout.addWidget(self.Zoom_outBtn)
self.vlayout.addWidget(self.Zoom_inBtn)
self.qwidget.setLayout(self.vlayout)
self.setCentralWidget(self.qwidget)
def zoomin(self):
print("zoom in")
global lvlofzoom
lvlofzoom = lvlofzoom *1.25
mousepos = self.Imagedisplay.mapFromGlobal(QCursor.pos())
mousepos = self.Imagedisplay.mapToScene(mousepos)
#mousepos = self.Imagedisplay.mapFromScene(QCursor.pos())
global qpixmap
pixmap_to_show = QGraphicspixmapItem(qpixmap)
pixmap_to_show.setTransformationMode(Qt.SmoothTransformation)
pixmap_to_show.setTransformOriginPoint(mousepos)
pixmap_to_show.setScale(lvlofzoom)
pixmap_scene = QGraphicsScene(self.Imagedisplay)
pixmap_scene.addItem(pixmap_to_show)
# pixmap_scene.
self.Imagedisplay.setScene(pixmap_scene)
def zoomout(self):
print("zoom out")
global lvlofzoom
lvlofzoom = lvlofzoom * 0.8
mousepos = self.Imagedisplay.mapFromGlobal(QCursor.pos())
mousepos = self.Imagedisplay.mapToScene(mousepos)
#mousepos = self.Imagedisplay.mapFromScene(QCursor.pos())
global qpixmap
pixmap_to_show = QGraphicspixmapItem(qpixmap)
pixmap_to_show.setTransformationMode(Qt.SmoothTransformation)
pixmap_to_show.setTransformOriginPoint(mousepos)
pixmap_to_show.setScale(lvlofzoom)
pixmap_scene = QGraphicsScene(self.Imagedisplay)
pixmap_scene.addItem(pixmap_to_show)
# pixmap_scene.
self.Imagedisplay.setScene(pixmap_scene)
def loadimg(self):
global qpixmap
print("load img")
fileName,_ = QtWidgets.QFileDialog.getopenFileName(None,"Select Image","","Image Files (*.png *.jpg *jpeg *.bmp)")
if fileName:
qpixmap = QtGui.Qpixmap(fileName)
qpixmap = qpixmap.scaledToWidth(self.Imagedisplay.width())
qgraphicsitem = QGraphicspixmapItem(qpixmap)
qscene = QGraphicsScene(self.Imagedisplay)
qscene.addItem(qgraphicsitem)
self.Imagedisplay.setScene(qscene)
self.Imagedisplay.setMouseTracking(True)
# self.ui.label_Pano.scene().
self.Imagedisplay.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.Imagedisplay.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.Imagedisplay.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBaralwaysOff)
self.Imagedisplay.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBaralwaysOff)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
我知道这是因为我从全局获取鼠标位置,并以鼠标的全局位置作为变换原点缩放整个图像。但是,即使将其映射到场景后,也无法按需要工作。
理想情况下,我想以不同的方式解决这个问题,通过缩放像素图本身来实现缩放功能。这是首选选项,因为它需要我重写最少的代码(更大的“宠物项目”的一部分,其他功能与缩放交互 - 例如:在缩放的同时在图像上绘制)。 请在下面找到zoomin 和loadimg 的重新植入(其余保持不变,除了部分无关的zoomout):
def zoomin(self):
print("zoom in")
global lvlofzoom
lvlofzoom = lvlofzoom *1.25
global qpixmap
mousepos = self.Imagedisplay.mapFromGlobal(QCursor.pos())
pixmap = qpixmap.scaledToWidth(int(self.Imagedisplay.width() * lvlofzoom))
pixmap_to_show = QGraphicspixmapItem(pixmap)
pixmap_scene = QGraphicsScene(self.Imagedisplay)
pixmap_scene.addItem(pixmap_to_show)
self.Imagedisplay.setScene(pixmap_scene)
def loadimg(self):
global qpixmap
print("load img")
fileName,"Image Files (*.png *.jpg *jpeg *.bmp)")
if fileName:
qpixmap = QtGui.Qpixmap(fileName)
qpixmap2 = qpixmap.scaledToWidth(self.Imagedisplay.width())
qgraphicsitem = QGraphicspixmapItem(qpixmap2)
qscene = QGraphicsScene(self.Imagedisplay)
qscene.addItem(qgraphicsitem)
self.Imagedisplay.setScene(qscene)
self.Imagedisplay.setMouseTracking(True)
self.Imagedisplay.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.Imagedisplay.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.Imagedisplay.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBaralwaysOff)
self.Imagedisplay.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBaralwaysOff)
我希望在 scaledtoWidth 上添加一个鼠标锚点,并将 self.Imagedisplay.width 与 lvlofzoom 或缩放 Imagedisplay 相乘,转换模式为 Qt.SmoothTransformation。
解决方法
通过使用 setSceneRect() 解决,由 eyllanesc (PyQt5: I can't understand QGraphicsScene's setSceneRect(x,y,w,h)) 的另一个答案指导
def zoomin(self):
print("zoom in")
global lvlofzoom
lvlofzoom = lvlofzoom *1.25
global qpixmap
mousepos = self.ImageDisplay.mapFromGlobal(QCursor.pos())
pixmap = qpixmap.scaledToWidth(int(self.ImageDisplay.width() * lvlofzoom))
pixmap_to_show = QGraphicsPixmapItem(pixmap)
pixmap_scene = QGraphicsScene(self.ImageDisplay)
pixmap_scene.addItem(pixmap_to_show)
p = self.ImageDisplay.mapToScene(QCursor.pos())#p0)
r = self.ImageDisplay.sceneRect()
r.moveCenter(p)
self.ImageDisplay.setScene(pixmap_scene)
self.ImageDisplay.setSceneRect(r)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。