【问题标题】:PyQt QGraphicsView pan and zoom with transform matrixPyQt QGraphicsView 使用变换矩阵平移和缩放
【发布时间】:2014-11-08 05:08:28
【问题描述】:

我正在尝试使用 QGraphics 变换矩阵进行平移和缩放。缩放工作正常,但平移参数 m31 和 m32 无效。看起来还有另一个功能使场景居中。在下面的代码中,我操作 rectScene 来进行平移,但为什么我不能使用 m31 和 m32 来平移? (这是我的问题

'''Pan (left mouse but) and zoom (mouse wheel)  test'''
'''Python 3.4 (No differance between PyQt4 and PyQt5)'''
#from PyQt5 import QtGui, QtCore
#import PyQt5.QtWidget as QW            
from PyQt4 import QtGui, QtCore
import PyQt4.QtGui as QW            

import numpy as np                         

class ZoomAndPan(QW.QGraphicsView):

    def __init__(self,parent=None):
        super(ZoomAndPan,self).__init__(parent)
        self.setWindowTitle('ZoomAndPan')
        self.setGeometry(600,300,600,400)
        'Left button in top of image. Shows the transform matrix (press to reset)'
        self.mess = QW.QPushButton('Transform Matrix\n\n\ndx,xy\ncounter', self)
        self.mess.clicked.connect(self.resetM)

        'm31 button, adds 200 to m31'
        self.m31 = QW.QPushButton('m31', self)
        self.m31.move(200,0)
        self.m31.clicked.connect(self.addM31)

        'm13 button, adds 0.0001 to m13'
        self.m13 = QW.QPushButton('m13', self)
        self.m13.move(300,0)
        self.m13.clicked.connect(self.addM13)
        self.count=0   #Counter     

        # Create scene   
        self.sc=scene(self,self)
        self.setScene(self.sc)

    def mouseMoveEvent(self,event):
        'Pan by manipulting sceneRect'
        pos=event.pos()
        pos=self.mapToScene(pos)      
        dx=pos.x()-self.sc.startPos.x() 
        dy=pos.y()-self.sc.startPos.y()

        rect=self.sceneRect().getRect()
        self.setSceneRect(rect[0]-dx,rect[1]-dy,rect[2],rect[3])         
        # Increas counter to show that the loop works 
        self.count+=1
        self.showMatrix()

    def showMatrix(self):
        'Show matrix in Textbox (Buttton)'
        m=self.transform()
        str1='{0:5.2f}{1:5.2f} {2:6.4f}\n'.format(m.m11(), m.m12(),m.m13())
        str2='{0:5.2f}{1:5.2f}{2:5.2f}\n'.format(m.m21(), m.m22(),m.m23())
        str3='{0:5.2f}{1:5.2f}{2:5.2f}\n'.format(m.m31(), m.m32(),m.m33())
        str4='{0:5.2f}{1:5.2f}\n'.format(m.dx(), m.dy(),m.m33())
        'Show counter '
        str5='{0:5.0f}'.format(self.count)        
        self.mess.setText(str1+str2+str3+str4+str5)

    def resetM(self):
        'Reset transform'
        self.resetTransform()
        self.showMatrix()

    def addM31(self):
        'Add 200 to m31 '
        m=self.transform()
        m.setMatrix(m.m11(),m.m12(),m.m13(),m.m21(),m.m22(),m.m23(),m.m31()+200,m.m32(),m.m33())
        self.setTransform(m)    
        self.showMatrix()

    def addM13(self):
        'Add 0.0001 to m13 '
        m=self.transform()
        m.setMatrix(m.m11(),m.m12(),m.m13()+0.0001,m.m21(),m.m22(),m.m23(),
            m.m31(),m.m32(),m.m33())
        self.setTransform(m)    
        self.showMatrix()        

class scene(QW.QGraphicsScene):
    def __init__(self,parent,myView=[]):
        QW.QGraphicsScene.__init__(self,parent)
        self.myView=myView        
        # Some items in scene 
        self.txt=self.addSimpleText("///////")
        self.txt.setPos(2,-20)
        self.txt.setScale(2)
        self.txt.setBrush(QtGui.QBrush(QtCore.Qt.green))
        self.addRect(0,16,20,20, pen=QtGui.QPen(QtCore.Qt.blue))
        self.addRect(10,60,32,8, pen=QtGui.QPen(QtCore.Qt.red))
        self.addRect(30,16,20,20, pen=QtGui.QPen(QtCore.Qt.blue))
        self.N=0

    def mousePressEvent(self, event):     
        self.myView.setDragMode(1) # Works fine without this   
        self.startPos=event.scenePos()        

    def mouseReleaseEvent(self, event):     
        self.myView.setDragMode(0)

    def wheelEvent(self, event):
        'zoom'
        sc=event.delta()/100
        if sc<0: sc=-1/sc
        self.myView.scale(sc,sc)
        self.myView.setDragMode(0)
        self.myView.showMatrix()        

def main():
    app = QW.QApplication([])
    fig=ZoomAndPan()
    fig.show();
    app.exec_()


if __name__=='__main__':
    main()

【问题讨论】:

    标签: pyqt qgraphicsview pan


    【解决方案1】:

    从数学的角度来看,一切正常。您看不到任何变化的原因是QGraphicsView 根据其alignment property 将视图居中。

    来自Qt docs

    QGraphicsView 支持仿射变换,使用 QTransform。您可以将矩阵传递给 setTransform(),也可以调用便利函数之一 rotate()、scale()、translate() 或 slice()。最常见的两种转换是用于实现缩放的缩放和旋转。 QGraphicsView 在转换过程中保持视图中心不变。由于场景对齐(setAligment()),平移视图不会产生视觉影响。

    【讨论】:

    • 好的,我检查了 Qt 文档。您可以将对齐方式设置为居中、上、下、左或右。是否可以关闭此功能?或者你可以覆盖这个函数吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2016-06-01
    • 2017-02-09
    • 2016-11-25
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多