在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. Vagrant将下载好的镜像装载到本地中

    Vagrant box add centos7 ${path}CentOS-7-x86_64-Vagrant-1803_01.VirtualBox Vagrant init ${名字} Vagrant ...

  2. servlet 会话技术

    一.控制器: 1.如何去确定需要一个新的控制器? 原则:一类事务请求需要一个控制器. 二.会话: 用户开一个浏览器,访问一个网站,只要该浏览器不关闭浏览器,不管该用户点击了多少个超链接,访问了多少个资 ...

  3. 关于python的GIL全局解释器锁的简单理解

    GIL是解释器内部的一把锁,确切一点说是CPython解释器内部的一把锁,所以要注意区分 这和我们在Python代码中使用线程锁Lock并不是一个层面的概念. 1. GIL产生的背景: 在CPytho ...

  4. poj3614 Sunscreen

    贪心题. 如何找出正确的贪心策略呢? 我一开始是以为按照l排序,然后从1到n遍历,挑最大的满足的防晒霜.后来发现不行.挑最小的也不行. 看了题解发现是从n到1遍历. 为什么? 因为i-1的l比i的l承 ...

  5. request的基本应用

    一.安装 pip install requests (mac前面加sudo) 二.requests的一些参数 method:一般是用的那种请求方法,是get还是post,delete或者delete ...

  6. Unity 后处理堆

    Unity安装后处理的过程:windows---PacageManager---Post Processing Post Processing后处理堆需要知道要修改那个相机渲染的内容,先定位到相机,再 ...

  7. position:fixed固定定位的用法

    一.position:fixed:固定定位 1.实现某个元素在可视窗口的居中位置显示 1)给自身设置宽高: 2)给自身加position:fixed: 3)用margin向左移动自身宽度的一半,向上移 ...

  8. Qt ------ 添加某个功能,比如(QSerialPort)注意事项

    添加某个功能,比如(QSerialPort),不仅需要保护头文件 还需要在.pro文件内添加 QT += serialport

  9. ttribute "xmlns" was already specified for element "web-app".

    今天导入了,一个javaweb项目,当自己对项目进行重命名的时候时候,但是web.xml直接爆出来一个"ttribute "xmlns" was already spec ...

  10. CodeForces1073E 数位dp+状压dp

    http://codeforces.com/problemset/problem/1073/E 题意 给定K,L,R,求L~R之间最多不包含超过K个数码的数的和. 显然这是一道数位dp,在做的过程中会 ...