在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(-,-,,)  #创建椭圆--场景坐标
#参数1 参数2 矩形左上角坐标
#参数3 参数4 矩形的宽和高

pyqtgraph的更多相关文章

  1. Python 图形 GUI 库 pyqtgraph

    原文  Python 图形 GUI 库 pyqtgraph pyqtgraph 是纯 Python 图形 GUI 库,基于PyQT4 /pyside和NumPy.它主要目的用于在数学/科学/工程中.M ...

  2. 【pyqtgraph绘图】案例-动态的正余弦波形图

    先看一个简单的小例子: 完整代码: import numpy as np import pyqtgraph as pg import sys from PyQt5.QtWidgets import Q ...

  3. 【pyqtgraph绘图】线条,填充和颜色

    解读官方API-线条,填充和颜色 参考: http://www.pyqtgraph.org/documentation/style.html 线条,填充和颜色 Qt依靠其QColor,QPen和QBr ...

  4. 【pyqtgraph绘图】在pyqtgraph中绘图

    解读pyqtgraph官方API-在pyqtgraph中绘图 参考: http://www.pyqtgraph.org/documentation/plotting.html 在pyqtgraph中绘 ...

  5. 【pyqtgraph绘图】Qt速成课程

    解读官方API-Qt速成课程 参考:http://www.pyqtgraph.org/documentation/qtcrashcourse.html Qt速成课程 PyQtGraph广泛使用Qt来生 ...

  6. 【pyqtgraph绘图】安装pyqtgraph

    解读官方API-安装 安装 参考:http://www.pyqtgraph.org/documentation/installation.html 根据您的需要,有许多不同的方式来安装pyqtgrap ...

  7. 【pyqtgraph绘图】如何使用pyqtgraph

    解读官方API-如何使用pyqtgraph 这里有一些使用pyqtgraph的建议方法: 从交互式shell(python -i,ipython等) 从应用程序显示弹出窗口 在PyQt应用程序中嵌入小 ...

  8. 【pyqtgraph】pyqtgraph-鼠标互动

    pyqtgraph绘图库官方文档学习-鼠标互动(mouse interaction) 鼠标互动 大多数使用pyqtgraph数据可视化的应用程序都会生成可以使用鼠标进行交互式缩放,平移和配置的小部件. ...

  9. 【PyQt5-Qt Designer】在GUI中使用pyqtgraph绘图库

    pyqtgraph绘图库 1.1 简介: pyqtgraph是Python平台上一种功能强大的2D/3D绘图库,相对于matplotlib库,由于内部实现方式上,使用了高速计算的numpy信号处理库以 ...

  10. python pyqtgraph 保存图片到本地

    pyqtgraph官方给的示例居然会报错2333 官方文档传送门:#####pyqtgraph export pyqtgraph支持在可视化窗口中右键保存(Exporting from the GUI ...

随机推荐

  1. multimap多重映照容器

    //multimap的基本用法 #include<map> #include<iostream> #include<string> using namespace ...

  2. java 连接数组

    一,使用Apache Commons的ArrayUtils Apache Commons类库有很多,几乎大多数的开源框架都依赖于它,Commons中的工具会节省你大部分时间,它包含一些常用的静态方法和 ...

  3. P1637 三元上升子序列

    thair 好,这个naive的东西因为只有三元,很好求解.只要把每个数之前小的L[i]与之后大的R[i]求一下即可. 求两次逆序对即可.那么答案便是∑(L[i]*R[i]); 对于更高元的,胡雨菲写 ...

  4. 【洛谷P4318】完全平方数

    题目大意:求第 K 个无平方因子数. 题解:第 k 小/大的问题一般采用二分的方式,通过判定从 1 到当前数中满足某一条件的数有多少个来进行对上下边界的转移. 考虑莫比乌斯函数的定义,根据函数值将整数 ...

  5. python常用的内置模块

    1.import time time模块与时间相关的功能 在python中时间分为3种 1.时间戳timestamp从1970 1月 1日到现在的秒数 主要用于计算两个时间的差 2.localtime ...

  6. 第二十九节,目标检测算法之R-CNN算法详解

    Girshick, Ross, et al. “Rich feature hierarchies for accurate object detection and semantic segmenta ...

  7. Failed to start Vsftpd ftp daemon错误

    配置 vsftpd.conf文件后 重启ftp服务出现 Failed to start Vsftpd ftp daemon错误 总是 启动失败 解决方法 将配置文件中的 listen=YES 改为 l ...

  8. 基于python调用libvirt API

    基于python调用libvirt API 1.程序代码 #!/usr/bin/python import libvirt import sys def createConnection(): con ...

  9. MySQL5.7 的GTID复制

    MySQL5.7 的GTID复制 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 在MySQL5.6之后其官方推出了GTID复制方式,和传统的基于bin log复制方式有所不同,接 ...

  10. PHP索引数组+unset使用不当导致的问题

    转自先知社区 https://xz.aliyun.com/t/2443 0x00前言 通常网站后台可以配置允许上传附件的文件类型,一般登录后台,添加php类型即可上传php文件getshell.但是, ...