• 第15.47节、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例


    一、概述

    Designer中的Graphics View部件是个图形视图部件,对应类为QGraphicsView,其功能不是简单的显示图形,老猿认为这是一种特殊的视图,它与QGraphicsScene配套实现了类似Model/View的架构。

    本节不介绍QGraphicsView和QGraphicsScene的所有属性、方法,大家可以参考官方文档,另外老猿推荐《Qt绘图之QGraphicsScene QGraphicsView QGraphicsItem详解》供大家参考。

    二、QGraphicsView功能简介

    QGraphicsView主要是用于界面显示图形的,显示的内容由QGraphicsScene决定。QGraphicsView支持鼠标的拖拽、点击、滚动等事件,可以根据滚动条策略控制滚动条的出现,提供视图、场景的坐标映射,支持设置对齐方式。

    具体属性、方法、信号可以参考官方文档以及上面推荐的博文,在此需要重点说明如下几点:

    1. QGraphicsView默认是带有内边距和边界,会导致内置于内的QGraphicsScene坐标与视图看到的效果不一致,具体请参考《QT:QGraphicsView QGraphicsScene QGraphicsItem理解
    2. QGraphicsView的坐标体系与QWidget的坐标体系相同,视口范围需要从其viewport视口属性获取
    3. QGraphicsView的场景可以从scene()方法获取,场景大小范围可以从sceneRect()获取
    4. QGraphicsView的默认是居中对齐的,所以如果添加显示对象,默认是显示在中央的

    三、QGraphicsScene功能简介

    QGraphicsScene用于管理一个需要绘制的图形对象,每个对象称为图元(基类为QGraphicsItem),如果理解QGraphicsScene为一个Model对象的话,QGraphicsItem就是Model中的项。

    QGraphicsItem具体属性、方法、信号可以参考官方文档以及上面推荐的博文,在此需要重点说明如下几点:

    1. QGraphicsScene的图元类型有多种,每种图元在添加时要调用专属的添加方法,方法会返回对应的图元类型对象。这些方法包括addLine()、addPath()、addPixmap()、 addRect()、 addText()、addEllipse()、addPolygon()、addSimpleText等
    2. QGraphicsScene的图元都可以通过setPos方法改变其位置,但需要注意,QGraphicsScene的坐标体系与QGraphicsView不同,具体请参考前面推荐的博文
    3. QGraphicsScene提供了大多数的鼠标和键盘等事件处理虚方法,如mousePressEvent、mouseMoveEvent、mouseReleaseEvent、mouseDoubleClickEvent、keyReleaseEvent、keyPressEvent等,可以通过子类化或者动态赋值方式接管相关的事件处理,从而实现对应的处理。但需要注意的是,这些方法中鼠标的位置应该通过scenePos()来获取,不能通过pos()来获取,pos是仅当鼠标点击了对应图元的时候才有值

    四、案例

    4.1、案例功能说明

    在案例中需要在界面上显示如下内容:
    在这里插入图片描述
    并实现除HELLO外的部分随鼠标点击移动位置。上面的内容包括图片、文字、直线、椭圆以及曲线。

    4.2、界面设计

    界面UI设计非常简单,就是一个窗口中放置了一个QGraphicsView,如图:
    在这里插入图片描述
    窗口命名为mainWin,图形视图命名为graphicsView。

    4.3、实现界面派生类构造方法

    构造方法中除了图形界面初始化外,还将图形视图的内边距和边界去除、改变图形视图的对齐方式、设置场景大小和图形视图大小一致,并绘制图形,同时接管图形场景的mousePressEvent 方法。具体代码如下:

    class mainWin(QtWidgets.QWidget,ui_mainWin.Ui_mainWin):
        def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.graphicsView.setStyleSheet("padding: 0px; border: 0px;")#内边距和边界去除
            self.scene = QtWidgets.QGraphicsScene(self)
            self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) #改变对齐方式
    
            self.graphicsView.setSceneRect(0,0,self.graphicsView.viewport().width(),self.graphicsView.height()) #设置图形场景大小和图形视图大小一致
            self.graphicsView.setScene(self.scene)
            self.addScenes() #调用绘制图形的方法
            self.scene.mousePressEvent = self.mousePressEvent  #接管图形场景的鼠标事件
    

    4.4、实现绘制图形的addScenes方法

        def addScenes(self): #绘制图形
            originX,originY = 40,60  #坐标基点
            self.itemHELLO = self.scene.addText("HELLO!")  #输出hello
            self.itemHELLO.setPos(0, 0)
    
            #绘制矩形
            pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.red))
            rectF = QtCore.QRectF(originX+300-8, originY-25, 20, 50)
            self.elpItem = self.scene.addEllipse(rectF, pen)
    
            # 绘制曲线
            pen.setColor(QtGui.QColor(QtCore.Qt.blue))
            path = QtGui.QPainterPath()
            path.moveTo(originX,originY)
            path.cubicTo(originX+100, originY-150, originX+200, originY+150,originX+300,originY)
            myGradient = QtGui.QLinearGradient()
            myFont = QtGui.QFont()
            textPoint = QtCore.QPointF(originX+35,originY-4)
            path.addText(textPoint, myFont, "老猿Python")
            self.itemPath = self.scene.addPath(path,pen,myGradient)
            #绘制下划线
            pen.setColor(QtGui.QColor(QtCore.Qt.darkRed))
            line = QtCore.QLineF(QtCore.QPointF(originX+190, originY-20), QtCore.QPointF(originX+275, originY-20))
            self.itemLine = self.scene.addLine(line, pen)
            self.itemLine.setPos(0,originY-20)
    
            #绘制文字
            self.itemText = self.scene.addText("跟老猿学Python!")
            self.itemText.setPos(originX+185,originY+1)
            
            #绘制图片
            pixmap = QtGui.QPixmap(r"F:coffeDog咖啡狗小图.jpg")
            self.pixmapItem = self.scene.addPixmap(pixmap)
            self.pixmapItem.setPos(originX-34,originY-16)
            
            #绘制x轴
            pen.setColor(QtGui.QColor(QtCore.Qt.red))
            self.xLine = self.scene.addLine(originX,originY, originX+300, originY, pen)
    

    4.5、实现鼠标按键响应myMousePressEvent方法

    注意这个方法不要命名为mousePressEvent,因为这样不但会接管图形场景的鼠标按键事件,而且会接管主窗口的鼠标按键事件,而二者的参数类型是不同的,对应属性也不同。

        def myMousePressEvent(self,mouseEvent):
            print("myMousePressEvent",mouseEvent.type(),mouseEvent.scenePos())
            point = mouseEvent.scenePos()
            if  point:
                self.movePath(point) #移动相关图元,方法单独实现
            else:print("not valid point")
    

    4.6、实现图元移动的movePath方法

    在该方法中需要将相关图元的位置同步移动,所以在绘制方法中记录下来了所有图元对象。移动图元是参考图片的坐标。

    4.7、运行效果

    在这里插入图片描述

    广告

    老猿关于PyQt的付费专栏《使用PyQt开发图形界面Python应用》只需要9.9元,该部分与第十五章的内容基本对应,但同样内容在付费专栏上总体来说更详细、案例更多。本节内容对应付费专栏的《第四十章、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例
    》。如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

    跟老猿学Python、学5G!

  • 相关阅读:
    SVN还原项目到某一版本(转)
    C# Web Service 不使用服务引用直接调用方法(转)
    动态调用webservice时 ServiceDescriptionImporter类在vs2010无法引用的解决方法 (转)
    log4net示例2-日志输入存入Access(转)
    C# log4net 配置及使用详解--日志保存到文件和Access(转)
    未能解析引用的程序集......因为它对不在当前目标框架“.NETFramework,Version=v4.0,Profile=Client”中的 (转)
    Hello log4net——做一个实用好用的log4net的demo(转)
    JS移动客户端--触屏滑动事件
    js生成二维码实例
    触屏版类似刷新页面文本框获取焦点的同时弹出手机键盘的做法
  • 原文地址:https://www.cnblogs.com/LaoYuanPython/p/12805854.html
Copyright © 2020-2023  润新知