微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 QGraphicsView 场景放大鼠标位置

如何解决使用 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 举报,一经查实,本站将立刻删除。