GUI编程—欢迎来到PyQtGraph-中文版(中)!

六、Qt 快速教学

几乎所有的PyQtGraph库的图形界面都是由Qt来生成。 Qt的文档写得很好,我们鼓励所有pyqtgraph开发人员熟悉它。 本节的目的是介绍如何使用Qt(使用PyQt或PySide)编写pyqtgraph开发者程序。

窗口和布局

Qt GUI几乎都是由几个基本组件组成:

  • 一个窗口。 这通常由QMainWindow提供,但请注意,如果窗口小部件没有父窗口,只需调用widget.show(),就可以在窗口中显示所有QWidgets。
  • 多个QWidget实例,如QPushButton,QLabel,QComboBox等
  • QLayout实例(可选,但强烈鼓励),它可以自动管理窗口小部件的位置,同时允许GUI以可调整的方式调整大小。

PyQtGraph通过提供自己的QWidget子类插入到你的GUI中来适应这个方案。

例如:

from PyQt4 import QtGui  # (the example applies equally well to PySide)
import pyqtgraph as pg

## Always start by initializing Qt (only once per application)
app = QtGui.QApplication([])

## Define a top-level widget to hold everything
w = QtGui.QWidget()

## Create some widgets to be placed inside
btn = QtGui.QPushButton('press me')
text = QtGui.QLineEdit('enter text')
listw = QtGui.QListWidget()
plot = pg.PlotWidget()

## Create a grid layout to manage the widgets size and position
layout = QtGui.QGridLayout()
w.setLayout(layout)

## Add widgets to the layout in their proper positions
layout.addWidget(btn, 0, 0)   # button goes in upper-left
layout.addWidget(text, 1, 0)   # text edit goes in middle-left
layout.addWidget(listw, 2, 0)  # list widget goes in bottom-left
layout.addWidget(plot, 0, 1, 3, 1)  # plot goes on right side, spanning 3 rows

## Display the widget as a new window
w.show()


## Start the Qt event loop
app.exec_()

更复杂的界面可以使用Qt Designer进行图形化设计,它可以简单的拖拽小部件到窗口中定义其外观。

命名约定

事实上pyqtgraph中的每个类都是Qt提供的基类的扩展。 在阅读文档时,请记住Qt的所有类都以字母“Q”开头,而pyqtgraph的类没有。 在阅读任何类的方法时,这样通常有助于查看使用了哪些Qt基类,然后查看Qt文档。

大多数Qt的类都定义了很难区别于常规方法的信号。几乎所有由pyqtgraph定义的信号显示都以’sig’开头,表示这些信号不是在Qt级定义。

在大多数情况下,以’Widget’结尾的类都是QWidget的子类,因此可以用作Qt窗口中的GUI元素。 以’Item’结尾的类是QGraphicsItem的子类,只能在QGraphicsView实例(如GraphicsLayoutWidget或PlotWidget)中显示。

信号、槽和事件

Qt通过执行其事件循环来检测用户交互并对其做出反应。

  • 事件循环中发生了什么?
  • 我什么时候需要使用QApplication.exec_()?
  • 我对事件循环执行有什么控制?(QApplication.processEvents)

GraphicsView and GraphicsItems

有关Qt GraphicsView体系结构的更多信息:http://qt-project.org/doc/qt-4.8/graphicsview.html

坐标系与转换

有关Qt GraphicsView中坐标系的更多信息:http://qt-project.org/doc/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system

七、在pyqtgraph中绘图

在pyqtgraph中绘制数据有几种基本的方法:

方法 描述
pyqtgraph.plot() 创建一个显示数据的新图形窗口
PlotWidget.plot() 将一组新数据添加到现有的绘图小部件
PlotItem.plot() 将一组新数据添加到现有的绘图小部件
GraphicsLayout.addPlot() 在网格中添加一个新的图形

所有这些方法都接收相同的基本参数,这些参数控制如何绘制数据和显示图形:

  • x - 可选的X数据; 如果未指定,则会自动生成一系列整数。
  • y - Y数据。
  • pen - 绘制绘图线时使用的笔,或者无以禁用线。
  • symbol - 描述用于每个点的符号形状的字符串。 可选地,这也可以是对于每个点具有不同符号的字符串序列。
  • symbolPen - 绘制符号轮廓时使用的笔(或笔序列)。
  • symbolBrush - 填充符号时使用的画笔(或画笔序列)。
  • fillLevel - 填充曲线下面的区域为该Y值。
  • brush - 填充曲线时使用的笔刷。

请参阅“绘图”示例来演示这些参数。

所有上述函数会将返回值给创建它的对象,允许进一步修改绘图和数据。

建立绘图类

显示绘图数据时有几种类型。 大多数这些类都是自动实例化的,但了解它们是如何组织和相互关联是非常有用的。 PyQtGraph很大程度上基于Qt的GraphicsView框架 - 如果您还不熟悉这一点,那么值得一读(但不是必需的)。 最重要的是:1)Qt GUI由QWidgets组成,2)称为QGraphicsView的特殊小部件用于显示复杂图形,3)QGraphicsItems定义在QGraphicsView中显示的对象。

  • 数据类(QGraphicsItem的所有子类)
    • PlotCurveItem - 显示给定x,y数据的绘图线
    • ScatterPlotItem - 显示给定x,y数据的点
    • PlotDataItem - 组合PlotCurveItem和ScatterPlotItem。上面讨论的绘图函数创建了这种类型的对象。
  • 容器类(QGraphicsItem的子类;包含其他QGraphicsItem对象,必须从GraphicsView中查看)
    • PlotItem - 包含用于显示数据的ViewBox以及用于显示轴和标题的AxisItems和标签。这是一个QGraphicsItem子类,因此只能在GraphicsView中使用
    • GraphicsLayout - 显示项目网格的QGraphicsItem子类。 这用于一起显示多个PlotItem。
    • ViewBox - 一个用于显示数据的QGraphicsItem子类。 用户可以使用鼠标缩放/平移ViewBox的内容。 通常,所有PlotData / PlotCurve / ScatterPlotItems都是在ViewBox中显示的。
    • AxisItem - 显示轴值,刻度和标签。 最常用于PlotItem。
  • 容器类(QWidget的子类;可能嵌入在PyQt GUI中)
    • PlotWidget - 显示一个PlotItem的GraphicsView的子类。 PlotItem提供的大多数方法也可以通过PlotWidget获得。
    • GraphicsLayoutWidget - 显示单个GraphicsLayoutItem的QWidget子类。 GraphicsLayoutItem提供的大多数方法也可以通过GraphicsLayoutWidget获得。

例子

有关更多信息,请参阅pyqtgraph附带的“plotting”和“PlotWidget”示例。

将x,y数据显示为散点图:

import pyqtgraph as pg
import numpy as np
x = np.random.normal(size=1000)
y = np.random.normal(size=1000)
pg.plot(x, y, pen=None, symbol='o')  ## setting pen=None disables line drawing

创建/显示一个绘图小部件,显示三条数据曲线:

import pyqtgraph as pg
import numpy as np
x = np.arange(1000)
y = np.random.normal(size=(3, 1000))
plotWidget = pg.plot(title="Three plot curves")
for i in range(3):
    plotWidget.plot(x, y[i], pen=(i,3))  ## setting pen=(i,3) automaticaly creates three different-colored pens

八、显示图像和视频

PyQtGraph将2D numpy数组显示为图像,并提供确定如何在屏幕上的numpy数据类型和RGB值之间进行转换的工具。 如果要显示常用图像和视频文件格式的数据,则需要先使用另一个库(PIL适用于图像和内置numpy转换)加载数据。

显示二维或三维数据最简单的方法是使用pyqtgraph.image()函数:

import pyqtgraph as pg
pg.image(imageData)

该函数将接受任何浮点数或整数数据类型,并显示包含数据的单个ImageView小部件。 此小部件包含用于确定图像数据如何转换为32位RGBa值的控件。 转换分两步进行(两者都是可选的):

  1. 缩放和偏移数据(通过选择显示的直方图上的黑暗/亮度级别)
  2. 使用查找表将数据转换为颜色(由渐变编辑器中显示的颜色确定)

如果数据是3D(时间,x,y),则时间轴将显示一个可以设置当前显示帧的滑块。 (如果数据中的坐标轴的排列方式不同,请使用numpy.transpose重新排列它们)

还有其他一些显示图像的方法:

  • ImageView类也可以直接实例化并嵌入到Qt应用程序中。
  • ImageItem的实例可以在ViewBoxGraphicsView中使用。
  • 为了获得更高的性能,请使用RawImageWidget

通过调用setImage()来显示一个新的帧,任何这些类都可以用来显示视频。 为了提高性能,图像处理系统使用scipy.weave生成编译库。 如果您的计算机具有可用的编译器,则编译器将自动尝试根据需要构建它所需的库。 如果失败,则会使用较慢的纯Python方法。

有关更多信息,请参阅上面列出的类和’VideoSpeedTest’,’ImageItem’,’ImageView’和’HistogramLUT’示例。

九、3D图像

PyQtGraph使用OpenGL提供3D场景图系统。 该系统功能强大,但仍处于开发早期阶段。 目前的功能包括:

  • 带缩放/旋转控件的3D视图控件(鼠标拖动和滚轮)
  • 场景图允许通过每项转换和父/子关系从场景添加/删除项目。
  • 三角网格
  • 基本网格计算函数:等值面,每顶点法线
  • 体积渲染项目
  • 网格/轴项目

基本用法示例:

## build a QApplication before building other widgets
import pyqtgraph as pg
pg.mkQApp()

## make a widget for displaying 3D objects
import pyqtgraph.opengl as gl
view = gl.GLViewWidget()
view.show()

## create three grids, add each to the view
xgrid = gl.GLGridItem()
ygrid = gl.GLGridItem()
zgrid = gl.GLGridItem()
view.addItem(xgrid)
view.addItem(ygrid)
view.addItem(zgrid)

## rotate x and y grids to face the correct direction
xgrid.rotate(90, 0, 1, 0)
ygrid.rotate(90, 1, 0, 0)

## scale each grid differently
xgrid.scale(0.2, 0.1, 0.1)
ygrid.scale(0.2, 0.1, 0.1)
zgrid.scale(0.1, 0.2, 0.1)

十、线,填充和颜色

Qt依靠它的QColor,QPen和QBrush类为所有绘图指定线条和填充样式。 在内部,pyqtgraph使用相同的系统,但也允许许多简写方法指定相同的样式选项。

pyqtgraph中的许多函数和方法接受指定线条样式(笔),填充样式(笔刷)或颜色的参数。 对于大多数这些函数参数,可能会使用以下值:

  • 表示颜色的单字符串(b,g,r,c,m,y,k,w)
  • (r,g,b)或(r,g,b,a)元组
  • 单灰度值(0.0 - 1.0)
  • (index,maximum)元组,用于自动迭代颜色(请参阅intColor)
  • QColor
  • QPen / QBrush在适当的地方

值得注意的是,使用mkPen()/ mkBrush()函数或使用Qt的QPen和QBrush类可以轻松构建更复杂的笔和画笔:

mkPen('y', width=3, style=QtCore.Qt.DashLine)          ## Make a dashed yellow line 2px wide
mkPen(0.5)                                             ## solid grey line 1px wide
mkPen(color=(200, 200, 255), style=QtCore.Qt.DotLine)  ## Dotted pale-blue line

有关’QPen’和’PenStyle’的更多线型选项,请参阅Qt文档,更多填充选项请参阅’QBrush’。 颜色也可以使用mkColor(),intColor(),hsvColor()或Qt的QColor类来构建。

默认背景和前景色

默认情况下,pyqtgraph为其绘图使用黑色背景,而轴,文本和绘图线使用灰色。 这些默认值可以使用pyqtgraph.setConfigOption()来更改:

import pyqtgraph as pg

## Switch to using white background and black foreground
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')

## The following plot has inverted colors
pg.plot([1,4,2,3,5])

(请注意,这必须在创建任何小部件之前设置)

十一、交互式数据选择控件

PyQtGraph包含图形项目,允许用户选择和标记数据区域。

线性选择和标记

两个类允许标记和选择一维数据:LinearRegionItemInfiniteLine。 第一个类LinearRegionItem可以添加到任何ViewBoxPlotItem中,以标记水平或垂直区域。 该区域可以拖动,边界边缘可以独立移动。 第二类InfiniteLine通常用于标记沿x或y轴的特定位置。 这些可能会被用户拖动。

二维选择和标记

要从图像中选择2D区域,pyqtgraph使用ROI类或其任何子类。 默认情况下,ROI只是显示一个矩形,可以由用户移动以标记特定区域(通常这将是图像的区域,但这不是必需的)。 为了允许ROI被调整大小或旋转,有几种方法可以添加可由用户拖动的句柄(addScaleHandleaddRotateHandle等)。 这些手柄可以放置在相对于ROI的任何位置,并且可以在任意中心点周围缩放/旋转ROI。 有几个ROI子类具有各种形状和交互模式。

要使用ROI和ImageItem自动提取图像数据的区域,请使用ROI.getArrayRegion。 ROI类使用affineSlice函数来执行此提取。

ROI也可以用作移动/旋转/缩放场景中的项目的控件,类似于大多数vetctor图形编辑应用程序。

有关更多信息,请参阅ROITypes示例。

你可能感兴趣的:(GUI编程)