在 PyQt5 中使用 Matplotlib 绘制 CSV 文件

Posted

技术标签:

【中文标题】在 PyQt5 中使用 Matplotlib 绘制 CSV 文件【英文标题】:Plotting a CSV file using Matplotlib in PyQt5 【发布时间】:2017-11-21 15:58:48 【问题描述】:

我正在尝试学习 PyQt5 并在 GUI 上显示 Matplotlib 绘图。现在,我正在尝试使用我的Menubar 中的加载按钮从 CSV 文件加载数据。我可以成功地做到这一点。我的问题是现在在图表上显示这些数据。这是我的代码:

import sys
from PyQt5.QtWidgets import (QMainWindow, QAction, qApp, QApplication, QPushButton, QDesktopWidget,
                            QLabel, QFileDialog, QWidget, QGridLayout, QMenu, QSizePolicy, QMessageBox, QWidget)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QCoreApplication, Qt
from win32api import GetSystemMetrics

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import numpy as np

import random

CURRENT_VERSION = 0.1

class Example(QMainWindow):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setWindowTitle('test')

        window_width = GetSystemMetrics(0)
        window_height = GetSystemMetrics(1)

        self.resize(0.6 * window_width, 0.6 * window_height)
        self.center()

        self.setWindowIcon(QIcon('Icon.png'))

        #inits
        self.openDirectoryDialog = ""
        self.data = np.empty(shape=(1,2), dtype=np.float)

        #Exit on menubar
        exitAct = QAction('&Exit', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit applicatiion')
        exitAct.triggered.connect(qApp.quit)

        #Open on menubar
        openAct = QAction('&Open', self)
        openAct.setShortcut('Ctrl+O')
        openAct.setStatusTip('Open Directory')
        openAct.triggered.connect(self.openFile)

        #menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)
        fileMenu.addAction(openAct)

        #Central
        centralwidget = QWidget(self)
        self.setCentralWidget(centralwidget)

        #Grid
        grid = QGridLayout(centralwidget)
        self.setLayout(grid)

        #Plot
        plotCan = PlotCanvas(self, width=5, height=4)
        grid.addWidget(plotCan , 0,1)

        #button
        btn = QPushButton("Load Data", centralwidget)
        btn.resize(btn.sizeHint())
        grid.addWidget(btn, 0,0)

        btn.clicked.connect(plotCan .plot(self.data))

        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def openFile(self):
        self.csvFile = QFileDialog.getOpenFileName(self, "Get Dir Path")[0]
        self.data = np.loadtxt(self.csvFile, delimiter=',', dtype='S')[2:].astype(np.float)

    def buttonpress(self):
        self.plot(self.data)

class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                QSizePolicy.Expanding,
                QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

    def plot(self, data = np.empty(shape=(1,2))):
        ax = self.figure.add_subplot(111)
        ax.plot(data[:,0],data[:,1], 'r-')
        ax.set_title('PyQt Matplotlib Example')
        self.draw()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = Example()
    sys.exit(app.exec_())

OpenFile 中,我有一个非常具体的案例,稍后我将对其进行概括,但我使用的是前两行是标题的 CSV 文件。目前,当我启动程序时,我得到了错误

Traceback (most recent call last):
  File "Plotter.py", line 115, in <module>
    w = Example()
  File "Plotter.py", line 23, in __init__
    self.initUI()
  File "Plotter.py", line 75, in initUI
    btn.clicked.connect(plotCav.plot(self.data))
TypeError: argument 1 has unexpected type 'NoneType'

我不明白,因为我已经初始化了数据。

【问题讨论】:

【参考方案1】:

QObject.connect() 函数需要一个可调用的参数。在编写btn.clicked.connect(plotCan.plot(self.data)) 时,您将调用结果传递给plotCan.plot(self.data)(默认情况下None,因为没有指定return),因此您收到的错误消息

由于您想将 self.data 变量与调用一起传递,一个简单的方法是使用 lambda

btn.clicked.connect(lambda: plotCan.plot(self.data))

这满足connect()函数,并将调用推迟到plotCan.plot()

【讨论】:

以上是关于在 PyQt5 中使用 Matplotlib 绘制 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Qt Designer 表单和 PyQt5 在 QWidget 中绘制 matplotlib 图形

无法在 pyqt5 中嵌入的 matplotlib 上绘制线条

为啥我不能在 pyqt5 gui 中嵌入的 matplotlib 颜色图中成功绘制感兴趣区域?

我无法使用 MatplotLib 生成图表以在 PyQt5 App 上绘图

如何在 Pyqt5 环境中使用 Pickle 保存 Matplotlib 图?

Matplotlib 和 PyQt5 绘图图