PyQt5快速开发与实战

9. 第9章 PyQt5 扩展应用

9.5 PyQtGraph在PyQt中的应用

PyQtGraph是纯 Python图形GUI库,它充分利用PyQt和 PySide的高质量的图形表现水平和NumPy的快速的科学计算与处理能力,在数学、科学和工程领域都有广泛的应用。PyQtGraph是免费的,并且是在MIT的开源许可下发布的。

PyQtGraph的主要目标:

  • 为数据、绘图、视频等提供快速、可交互的图形显示。
  • 提供快速开发应用的工具。

尽管目前PyQtGraph还没有Matplotlib成熟,但是 PyQtGraph 比 Matplotlib 要快得多,尤其是在显示时间序列的实时行情图时,Matplotlib 在性能上有些捉襟见肘。PyQtGraph有自己的特殊应用,如图形交互、参数树、流程图等。由于PyQtGraph是基于PyQt开发的集成绘图模块,所以使用PyQtGraph绘图与通过底层方式来实现PyQt的绘图功能在速度上没有太大的区别。

9.5.1 PyQtGraph的安装
pip install pyqtgraph -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述

9.5.2 官方示例

在这里插入图片描述

在这里插入图片描述

核心代码

在这里插入图片描述

9.5.3 设置提升的窗口控件

在这里插入图片描述

在这里插入图片描述

ui转py

在这里插入图片描述

9.5.4 PyQtGraph的使用

程序初始化设置

class MainWindow(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)

        pg.setConfigOption('background', '#f0f0f0')  # 设置背景为灰色
        pg.setConfigOption('foreground', 'd')  # 设置前景(包括坐标轴,线条,文本等等)为黑色。

        pg.setConfigOptions(antialias=True) # 使曲线看起来更光滑,而不是锯齿状
        # pg.setConfigOption('antialias',True) # 等价于上一句,所不同之处在于setconfigOptions可以传递多个参数进行多个设置,而setConfigOption一次只能接受一个参数进行一个设置。
        self.setupUi(self)

绘图部分

@pyqtSlot()
def on_pushButton_clicked(self):
    """
    Slot documentation goes here.
    """
    self.pyqtgraph1.clear() # 清空里面的内容,否则会发生重复绘图的结果

    '''第一种绘图方式'''
    self.pyqtgraph1.addPlot(title="绘图单条线", y=np.random.normal(size=100), pen=pg.mkPen(color='b', width=2))

    '''第二种绘图方式'''
    plt2 = self.pyqtgraph1.addPlot(title='绘制多条线')

    plt2.plot(np.random.normal(size=150), pen=pg.mkPen(color='r', width=2), name="Red curve") # pg.mkPen的使用方法,设置线条颜色为红色,宽度为2。
    plt2.plot(np.random.normal(size=110) + 5, pen=(0, 255, 0), name="Green curve")
    plt2.plot(np.random.normal(size=120) + 10, pen=(0, 0, 255), name="Blue curve")


@pyqtSlot()
def on_pushButton_2_clicked(self):
    """
    Slot documentation goes here.
    """
    '''如果没有进行第一次绘图,就开始绘图,然后做绘图标记,否则就什么都不做'''
    try:
        self.first_plot_flag # 检测是否进行过第一次绘图。
    except:

        plt = self.pyqtgraph2.addPlot(title='绘制条状图')
        x = np.arange(10)
        y1 = np.sin(x)
        y2 = 1.1 * np.sin(x + 1)
        y3 = 1.2 * np.sin(x + 2)

        bg1 = pg.BarGraphItem(x=x, height=y1, width=0.3, brush='r')
        bg2 = pg.BarGraphItem(x=x + 0.33, height=y2, width=0.3, brush='g')
        bg3 = pg.BarGraphItem(x=x + 0.66, height=y3, width=0.3, brush='b')

        plt.addItem(bg1)
        plt.addItem(bg2)
        plt.addItem(bg3)

        self.pyqtgraph2.nextRow()

        p4 = self.pyqtgraph2.addPlot(title="参数图+显示网格")
        x = np.cos(np.linspace(0, 2 * np.pi, 1000))
        y = np.sin(np.linspace(0, 4 * np.pi, 1000))
        p4.plot(x, y, pen=pg.mkPen(color='d', width=2))
        p4.showGrid(x=True, y=True) # 显示网格

        self.first_plot_flag = True # 第一次绘图后进行标记

运行

在这里插入图片描述

9.5.5 更多扩展

在官方示例中,修改代码,完成扩展

import pyqtgraph.examples

pyqtgraph.examples.run()
9.6 Plotly在PyQt中的应用

Plotly本质上是基于 JavaScript 的图表库,支持不同类型的图表,如地图、箱形图、密度图,以及比较常见的条状图和线形图等。从2015年11月17日开始,Plotly个人版本可以免费使用了。

9.6.1 Plotly的安装
pip install plotly -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述

9.6.2 示例

使用QWebEngineView与Plotly完成交互

# -*- coding: utf-8 -*-

"""
Module implementing MainWindow.
"""

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
from PyQt5.QtWebEngineWidgets import QWebEngineView


class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.qwebengine = QWebEngineView(self)
        self.qwebengine.setGeometry(QRect(50, 20, 1200, 600))
        self.qwebengine.load(QUrl.fromLocalFile('D:\DingJiaxiong\PycharmProjects\PyQt5Study\Plotly在PyQt中的应用\plotly_html\if_hs300_bais.html'))


app = QApplication(sys.argv)
screen = Window()
screen.showMaximized()
sys.exit(app.exec_())

在这里插入图片描述

9.6.3 设置提升的窗口控件

在这里插入图片描述

UI.py

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.qwebengine = QWebEngineView(self.centralwidget)
        self.qwebengine.setGeometry(QtCore.QRect(10, 30, 451, 321))
        self.qwebengine.setAutoFillBackground(False)
        self.qwebengine.setStyleSheet("background-color: rgb(170, 170, 127);")
        self.qwebengine.setObjectName("qwebengine")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

from PyQt5.QtWebEngineWidgets import QWebEngineView
9.6.4 Plotly_PyQt5的使用
import pandas as pd
import os
import plotly.offline as pyof
import plotly.graph_objs as go

import numpy as np
import matplotlib.pyplot as plt


class Plotly_PyQt5():
   def __init__(self):
      plotly_dir = 'plotly_html'
      if not os.path.isdir(plotly_dir):
         os.mkdir(plotly_dir)
         
      self.path_dir_plotly_html = os.getcwd() + os.sep + plotly_dir
      
   def get_plotly_path_if_hs300_bais(self,file_name='if_hs300_bais.html'):
      path_plotly = self.path_dir_plotly_html + os.sep + file_name
      df = pd.read_excel(r'if_index_bais.xlsx')
      
      '''绘制散点图'''
      line_main_price = go.Scatter(
         x=df.index,
         y=df['main_price'],
         name='main_price',
         connectgaps=True, # 这个参数表示允许连接数据缺口
      )
      
      line_hs300_close = go.Scatter(
         x=df.index,
         y=df['hs300_close'],
         name='hs300_close',
         connectgaps=True,
      )
      data = [line_hs300_close,line_main_price]

      layout = dict(title='if_hs300_bais',
                 xaxis=dict(title='Date'),
                 yaxis=dict(title='Price'),
                 )

      fig = go.Figure(data=data, layout=layout)  
      pyof.plot(fig, filename=path_plotly, auto_open=False)
      return path_plotly
      
   def get_plot_path_matplotlib_plotly(self,file_name='matplotlib_plotly.html'):
      path_plotly = self.path_dir_plotly_html + os.sep + file_name

      N = 50
      x = np.random.rand(N)
      y = np.random.rand(N)
      colors = np.random.rand(N)
      area = np.pi * (15 * np.random.rand(N)) ** 2  # 0 to 15 point radii
      scatter_mpl_fig = plt.figure()
      plt.scatter(x, y, s=area, c=colors, alpha=0.5)

      pyof.plot_mpl(scatter_mpl_fig, filename=path_plotly, resize=True,auto_open=False)
      return path_plotly

主程序

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow

from Ui_plotly_pyqt import Ui_MainWindow

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
from Plotly_PyQt5 import Plotly_PyQt5


class MainWindow(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """

    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.plotly_pyqt5 = Plotly_PyQt5()
        self.qwebengine.setGeometry(QRect(50, 20, 1200, 600))
        self.qwebengine.load(QUrl.fromLocalFile(self.plotly_pyqt5.get_plotly_path_if_hs300_bais()))


app = QApplication(sys.argv)
win = MainWindow()
win.showMaximized()
app.exec_()

运行

在这里插入图片描述

9.6.5 更多扩展

https://plot.ly/python

根据相关案例,修改函数,得到想要的绘图结果

9.6.6 Plotly与PyQt5.6的结合

使用QWebView与Plotly进行交互

在这里插入图片描述

在新版本里面,官方已经把QtWebKitWidgets这个东西移除了

在这里插入图片描述

使用QtWebEngineWidgets替代它

ui.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'plotly_matplotlib_pyqt.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
        self.webView.setGeometry(QtCore.QRect(50, 50, 300, 200))
        self.webView.setUrl(QtCore.QUrl("about:blank"))
        self.webView.setObjectName("webView")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

from PyQt5 import QtWebEngineWidgets

调用主程序

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow

from Ui_plotly_matplotlib_pyqt import Ui_MainWindow

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
from Plotly_PyQt5 import Plotly_PyQt5


class MainWindow(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """

    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.plotly_pyqt5 = Plotly_PyQt5()
        self.webView.setGeometry(QRect(50, 20, 1200, 600))
        self.webView.load(QUrl.fromLocalFile(self.plotly_pyqt5.get_plot_path_matplotlib_plotly()))


app = QApplication(sys.argv)
win = MainWindow()
win.showMaximized()
app.exec_()

运行

在这里插入图片描述

报错了,跟着找过去

在这里插入图片描述

意思好像这个不能用了

开始谷歌…

在这里插入图片描述

找到这个了

仿佛是版本问题

在这里插入图片描述

啊这

在这里插入图片描述

好的,那就把版本降到3.2

在这里插入图片描述

在这里插入图片描述

再试一次

在这里插入图片描述

完美解决。

9.6.7 更多扩展

https://matplotlib.org/stable/gallery/index.html

在官网获取示例,修改在这里插入图片描述

这个函数,使用QWebEngineView间接实现交互。

Logo

鸿蒙生态一站式服务平台。

更多推荐