zoukankan      html  css  js  c++  java
  • pyqt5--QGraphicsView

    在Qt界面库中,对于图形的绘制,在前面介绍了一种使用QPainter实现普通二维图形的绘制方法,该方法在paintEvent事件里编写绘图程序,其本质绘制的图形是位图,这种方法更适合于绘制复杂度不高的固定图形,并且不能实现图项的选择、编辑、拖放、修改等交互功能。

    对于需要绘制大量的、需要交互的图形,可使用Graphics View绘图架构,它是一种基于图形项(Graphics Item)的模型/视图模式,这种方式可以在一个场景中可绘制大量图元项,且每个图元项都是可选择、可交互的。

    在Graphics View绘图架构中,主要涉及到下面三个类的使用:

    1. 场景类(QGraphicsScene):该类提供绘图场景(Scene),场景是不可见的,是一个抽象的管理图形项的容器,可向场景中添加图形项,获取场景中的某个图形项等;

    2. 视图类(QGraphicsView):该类提供绘图的视图(View)组件,用于显示场景中的内容。可以为一个场景设置几个视图,用于对同一个数据集提供不同的观察方式;

    3. 图形项类(QGraphicsItem):该类提供了一些基本的图形元件,也可在此基础上自定义图形项,它支持各种事件的响应,如鼠标事件、键盘事件、拖放事件等,以实现图形的交互功能

    在Graphics View绘图架构中涉及到了3个坐标系,即场景坐标、视图坐标及图形项坐标。其中,场景坐标类似于QPainter的逻辑坐标,一般以场景的中心为原点;视图坐标是窗口界面的物理坐标,其左上角为原点坐标;图形项坐标是局部逻辑坐标,通常以图件的中心为原点

    坐标实例

    import sys
    from PyQt5.QtWidgets import QApplication,QGraphicsScene,QGraphicsView,QGraphicsRectItem,QMainWindow,QLabel,QGraphicsItem,QGraphicsEllipseItem
    from PyQt5.QtCore import Qt,pyqtSignal,QPoint,QRectF
    
    class QMyGraphicsView(QGraphicsView):
        sigMouseMovePoint=pyqtSignal(QPoint)
        #自定义信号sigMouseMovePoint,当鼠标移动时,在mouseMoveEvent事件中,将当前的鼠标位置发送出去
        #QPoint--传递的是view坐标
        def __init__(self,parent=None):
            super(QMyGraphicsView,self).__init__(parent)
    
        def mouseMoveEvent(self, evt):
            pt=evt.pos()  #获取鼠标坐标--view坐标
            self.sigMouseMovePoint.emit(pt) #发送鼠标位置
            QGraphicsView.mouseMoveEvent(self, evt)
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.resize(600,400)
            self.view=QMyGraphicsView()  #创建视图窗口
            self.setCentralWidget(self.view) # 设置中央控件
            self.statusbar=self.statusBar()  #添加状态栏
            self.labviewcorrd=QLabel('view坐标:')
            self.labviewcorrd.setMinimumWidth(150)
            self.statusbar.addWidget(self.labviewcorrd)
            self.labscenecorrd=QLabel('scene坐标:')
            self.labscenecorrd.setMinimumWidth(150)
            self.statusbar.addWidget(self.labscenecorrd)
            self.labitemcorrd = QLabel('item坐标:')
            self.labitemcorrd.setMinimumWidth(150)
            self.statusbar.addWidget(self.labitemcorrd)
            rect=QRectF(-200,-100,400,200)
            self.scene=QGraphicsScene(rect)  #创建场景
            #参数:场景区域
            #场景坐标原点默认在场景中心---场景中心位于界面中心
            self.view.setScene(self.scene)  #给视图窗口设置场景
            item1=QGraphicsRectItem(rect)  #创建矩形---以场景为坐标
            item1.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable|QGraphicsItem.ItemIsMovable)  #给图元设置标志
            #QGraphicsItem.ItemIsSelectable---可选择
            #QGraphicsItem.ItemIsFocusable---可设置焦点
            #QGraphicsItem.ItemIsMovable---可移动
            #QGraphicsItem.ItemIsPanel---
            self.scene.addItem(item1)  #给场景添加图元
            for pos,color in zip([rect.left(),0,rect.right()],[Qt.red,Qt.yellow,Qt.blue]):
                item=QGraphicsEllipseItem(-50,-50,100,100)  #创建椭圆--场景坐标
                #参数1 参数2  矩形左上角坐标
                #参数3 参数4 矩形的宽和高
                item.setPos(pos,0)  #给图元设置在场景中的坐标(移动图元)--图元中心坐标
                item.setBrush(color)  #设置画刷
                item.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable|QGraphicsItem.ItemIsMovable)
                self.scene.addItem(item)
            self.scene.clearSelection()  #【清除选择】
            self.view.sigMouseMovePoint.connect(self.slotMouseMovePoint)
    
        def slotMouseMovePoint(self,pt):
            self.labviewcorrd.setText('view坐标:{},{}'.format(pt.x(),pt.y()))
            ptscene=self.view.mapToScene(pt)  #把view坐标转换为场景坐标
            self.labscenecorrd.setText('scene坐标:{:.0f},{:.0f}'.format(ptscene.x(),ptscene.y()))
            item=self.scene.itemAt(ptscene,self.view.transform())  #在场景某点寻找图元--最上面的图元
            #返回值:图元地址
            #参数1 场景点坐标
            #参数2 ????
            if item != None:
                ptitem=item.mapFromScene(ptscene)  #把场景坐标转换为图元坐标
                self.labitemcorrd.setText('item坐标:{:.0f},{:.0f}'.format(ptitem.x(),ptitem.y()))
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        ex = MainWindow()
        ex.show()
        sys.exit(app.exec_())
    
    
    import sys
    from PyQt5.QtWidgets import QWidget, QApplication,QGraphicsScene,QGraphicsView
    import time

    class Example(QWidget):
    def __init__(self):
    super().__init__()
    self.resize(500,400)
    scene=QGraphicsScene(self) #创建场景
    self.t=scene.addText("Hello, world!") #在场景中添加文本
    view=QGraphicsView(scene,self) #创建视图窗口
    view.move(10,10)
    view.show() #显示

    if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())
     

    添加文本图元

    font=QFont("华文琥珀",20,QFont.Bold)
    t=scene.addText("Hello, world!",font) #在场景中添加文本图元
    #参数1 文本
    #参数2 字体

    添加矩形

    pen = QPen()
            pen.setColor(Qt.blue)
            pen.setWidth(3)
            brush = QBrush(Qt.SolidPattern)
            brush.setColor(Qt.yellow)
            rect = QRectF(130,130,100,150)
            juxin=scene.addRect(30,30,100,100,pen,brush)  #添加矩形图元--方式一
            #参数1--参数4  坐标和宽高---以View为坐标系
            #参数5 画笔
            #参数6 画刷
            juxin = scene.addRect(rect, pen, brush)  # 添加矩形图元--方式二
    rect = QRectF(0,0,100,100)
            item1 = QGraphicsRectItem(rect)  # 创建矩形---以场景为坐标
            scene.addItem(item1)

    添加线段

    pen = QPen()
            pen.setColor(Qt.blue)
            pen.setWidth(3)
            line=scene.addLine(0,0,50,50,pen)  #添加直线--方式一
            lf=QLineF(50,50,0,50)
            line = scene.addLine(lf, pen)    #添加直线--方式二

    添加椭圆 

    item = QGraphicsEllipseItem(10, 10, 100, 100)  # 创建椭圆--场景坐标
            # 参数1 参数2  矩形左上角坐标
            # 参数3 参数4 矩形的宽和高
    scene.addItem(item)
    item=scene.addEllipse(10, 10, 100, 100,pen,brush)
    rect=QRectF(10, 10, 100, 100)
    item=scene.addEllipse(rect,pen,brush)

    图元的操作(缩放,平移,旋转)

    想要旋转,平移,缩放窗口中的图元,一般有两种思路:

    1. 操作View,概念类似于旋转摄像头,从而获取对场景Scene的不同观察结果,这样操作的好处是,场景中的图元本质上没有发生任何的变化,仅仅改变了View的计算矩阵,效率非常高,并且,如果该Scene被多个View绑定观察,对单独一个view的操作,将不会影响到别的view的观察结果

    2.操作Scene中所有的图元Item或者直接操作单个图元Item,概念类似于真实改变了场景中的各个物体的摆放方式,该方法使用的场合位:当一个场景,被多个view观察的时候,场景中的某一个变化操作,需要被这多个view同时观察到

    下面是操作图元的方法

    1. 图元的缩放:

    rect=QRectF(100, 100, 200, 100)
    item=scene.addEllipse(rect,pen,brush)
    item.setScale(0.5)  #对图元进行缩放
         #参数为图元大小的缩放比
         #需要注意的是,该方法的缩放基准是固定的,也就是说,如果连续两次调用该方法,但是参数的数字一样的话,第二次的调用将不会改变图元的大小
    print(item.scale())  #返回图元的缩放比

    2.图元的平移 

    item=scene.addRect(200,200,200,100,pen,brush)
    item.setPos(100,50)  #移动图元--方式一
            #参数 移动的偏移量
            #其传参的x与y坐标值,属于场景Scene的坐标,如果调用的时候,坐标来源于view的鼠标点击事件的坐标,需要调用mapToScene()将view坐标值转换到场景坐标
    item.moveBy(100,50)  #移动图元--方式二

    3.图元的旋转

    import sys
    from PyQt5.QtWidgets import QWidget, QApplication,QGraphicsScene,QGraphicsView,QGraphicsRectItem,QGraphicsEllipseItem,QGraphicsItem,QPushButton
    from PyQt5.QtGui import QPen,QBrush
    from PyQt5.QtCore import Qt,QRectF,QLineF
    
    class Example(QWidget):
        def __init__(self):
            super().__init__()
            self.resize(500,400)
            scene=QGraphicsScene()  #创建场景
    
            scene.setSceneRect(0,0,600,500)  #设置场景的坐标原点和宽高
            pen = QPen()
            pen.setColor(Qt.blue)
            pen.setWidth(3)
            brush=QBrush(Qt.yellow)
    
            item1=scene.addRect(0,0,250,25,pen,brush)
    
            item=scene.addRect(100,100,200,100,pen,brush)
            item.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)
            item.setPos(-100, -100)
            item.setTransformOriginPoint(0,0)  #设置旋转中心----???不按这点旋转啊
            #默认 图元的左上角
            #该方法传参的坐标值为图元自身的坐标系
            item.setRotation(30)  #旋转图元
            #参数 角度
            #正数 逆时针
            #设置的值的基准也是不变的,也就是说,连续两次调用该方法,都传入相同的参数值,图元只会旋转一次
            print(item.rotation())  #返回旋转角度
    
    
            view=QGraphicsView(scene,self)  #创建视图窗口
            view.resize(500,400)
            view.show()  #显示
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        ex = Example()
        ex.show()
        sys.exit(app.exec_())

    天子骄龙

    item=QGraphicsEllipseItem(-50,-50,100,100)  #椭圆--景坐
    #参数1 参数2 矩形左上角坐
    #参数3 参数4 矩形的和高
  • 相关阅读:
    python json.dumps() json.dump()的区别
    geopy 在python中的使用
    socket技术详解(看清socket编程)
    数据结构之各种数据结构插入、删除、查找的时间复杂度
    数组查找的时间复杂度正确表述
    各种排序算法时间复杂度
    MySQL将一张表的某些列数据,复制到另外一张表,并且修改某些内容
    Java虚拟机学习
    Java虚拟机学习
    java集合框架05——ArrayList和LinkedList的区别
  • 原文地址:https://www.cnblogs.com/liming19680104/p/10634642.html
Copyright © 2011-2022 走看看