第15.47节、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例
一、概述
Designer中的Graphics View部件是个图形视图部件,对应类为QGraphicsView,其功能不是简单的显示图形,老猿认为这是一种特殊的视图,它与QGraphicsScene配套实现了类似Model/View的架构。
本节不介绍QGraphicsView和QGraphicsScene的所有属性、方法,大家可以参考官方文档,另外老猿推荐《Qt绘图之QGraphicsScene QGraphicsView QGraphicsItem详解》供大家参考。
二、QGraphicsView功能简介
QGraphicsView主要是用于界面显示图形的,显示的内容由QGraphicsScene决定。QGraphicsView支持鼠标的拖拽、点击、滚动等事件,可以根据滚动条策略控制滚动条的出现,提供视图、场景的坐标映射,支持设置对齐方式。
具体属性、方法、信号可以参考官方文档以及上面推荐的博文,在此需要重点说明如下几点:
- QGraphicsView默认是带有内边距和边界,会导致内置于内的QGraphicsScene坐标与视图看到的效果不一致,具体请参考《QT:QGraphicsView QGraphicsScene QGraphicsItem理解》
- QGraphicsView的坐标体系与QWidget的坐标体系相同,视口范围需要从其viewport视口属性获取
- QGraphicsView的场景可以从scene()方法获取,场景大小范围可以从sceneRect()获取
- QGraphicsView的默认是居中对齐的,所以如果添加显示对象,默认是显示在中央的
三、QGraphicsScene功能简介
QGraphicsScene用于管理一个需要绘制的图形对象,每个对象称为图元(基类为QGraphicsItem),如果理解QGraphicsScene为一个Model对象的话,QGraphicsItem就是Model中的项。
QGraphicsItem具体属性、方法、信号可以参考官方文档以及上面推荐的博文,在此需要重点说明如下几点:
- QGraphicsScene的图元类型有多种,每种图元在添加时要调用专属的添加方法,方法会返回对应的图元类型对象。这些方法包括addLine()、addPath()、addPixmap()、 addRect()、 addText()、addEllipse()、addPolygon()、addSimpleText等
- QGraphicsScene的图元都可以通过setPos方法改变其位置,但需要注意,QGraphicsScene的坐标体系与QGraphicsView不同,具体请参考前面推荐的博文
- 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!
第15.47节、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例的更多相关文章
- 第四十章、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer中的Graphics V ...
- 第15.38节 PyQt(Python+Qt)入门学习:containers容器类部件QDockWidget停靠窗功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QDockWidget类提供了一个可以停靠在QMainWin ...
- 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...
- 第15.30节 PyQt编程实战:通过eventFilter监视QScrollArea的widget()的Paint消息画出scrollAreaWidgetContents的范围矩形
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 在<PyQt(Python+Qt)学习随笔:QScrollArea滚动区域详解> ...
- 第15.25节 PyQt(Python+Qt)入门学习:Model/View开发实战--使用QTableView展示Excel文件内容
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在前面的订阅专栏<第十九章.Model/View开发:QTableView的功能及属 ...
- 第15.18节 PyQt(Python+Qt)入门学习:Model/View架构中视图Item Views父类详解
老猿Python博文目录 老猿Python博客地址 一.概述 在PyQt图形界面中,支持采用Model/View架构实现数据和界面逻辑分离,其中Model用于处理数据存储,View用于界面数据展现,当 ...
- 第15.9节 PyQt学习入门:使用Qt Designer进行GUI设计的步骤
在使用Qt Designer进行GUI设计时,一般常规的步骤都是差不多的,主要步骤包括新建显示窗口.在窗口上按照规划的布局放置组件.设置初始化组件的属性.定义信号和槽函数的连接,一般后三步是每增加一个 ...
- 第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍
一. 引言 在上节<第15.6节 PyQt5安装与配置>结束了PyQt5的安装和配置过程,本节将编写一个简单的PyQt5应用,介绍基本的PyQt5应用的文件组成及相关工具的使用. 本节的应 ...
- 第15.17节 PyQt(Python+Qt)入门学习:PyQt图形界面应用程序的事件捕获方法大全及对比分析
老猿Python博文目录 老猿Python博客地址 按照老猿规划的章节安排,信号和槽之后应该介绍事件,但事件在前面的随笔<PyQt(Python+Qt)实现的GUI图形界面应用程序的事件捕获方法 ...
随机推荐
- 【Kata Daily 190912】Alphabetical Addition(字母相加)
题目: Your task is to add up letters to one letter. The function will be given a variable amount of ar ...
- EF6 Code First 博客学习记录
学习一下ef6的用法 这个学习过程时按照微软官网的流程模拟了一下 就按照下面的顺序来写吧 1.连接数据库 自动生成数据库 2.数据库迁移 3.地理位置以及同步/异步处理(空了再补) 4.完全自动迁移 ...
- !!vue-style-loader!css-loader?
摘自:https://blog.csdn.net/qq_27721169/article/details/88666340 问题描述*!!vue-style-loader!css-loader?{&q ...
- .Net核心依赖项注入:生命周期和最佳实践
在讨论.Net的依赖注入(DI)之前,我们需要知道我们为什么需要使用依赖注入 依赖反转原理(DIP): DIP允许您将两个类解耦,否则它们会紧密耦合,这有助于提高可重用性和更好的可维护性 DIP介绍: ...
- kafka消费者offset存储策略
由于 consumer 在消费过程中可能会出现断电宕机等故障,consumer 恢复后,需要从故 障前的位置的继续消费,所以 consumer 需要实时记录自己消费到了哪个 offset,以便故障恢 ...
- shell编程之输入输出
1.输入 read命令有以下几种常见形式: read var :等待用户输入,从标准输入中读取一行并赋值给变量var read : 标准输入读取一行,并赋值给内置变量REPLY read -a a ...
- UNP——第四章,TCP套接字编程
1.socket 函数 首先被调用的函数,用于选择通信协议. socket调用成功后,得到的套接字为主动套接字CLOSED状态. PF 和 AF 的关系 PF的是协议族,AF是地址族,理论上一个PF包 ...
- 用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!
一.收到了大佬们的建议 1.篇幅偏短,建议稍微加长一点. 这点说的确实挺对,有的篇幅确实比较短,针对这个提议我会考虑将相似的话题放在一篇文章中.但是这可能会导致我中断每天更新的步调,换成隔几天发一篇的 ...
- IDEA 2019.3.3 + Pycharm 2020.2.1 安装包及破解步骤
IDEA IDEA的破解流程就不用再说了,免费试用,添加VMOptions参数,选择破解jar的路径,重启IDEA. 下载地址:链接:https://pan.baidu.com/s/1aTRATVTL ...
- metasploit数据库使用学习
metasploit为了方便,自动将当前工作区的内容放入数据库 首先就是工作区 -a 增加工作区,-d删除工作区 不同工作区的内容会分开储存到数据库 default工作区 test工作区 db_imp ...