简体   繁体   中英

Plotting a CSV file using Matplotlib in PyQt5

I'm trying to learn PyQt5 and showing Matplotlib plots on a GUI. Right now, I'm trying to load data with a load button in my Menubar from a CSV file. I can do this successfully. My problem is with displaying this data on a chart now. Here is my code:

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_())

In OpenFile I have a very specific case that I will generalize later, but I'm using a CSV file where the first two rows are headers. Currently, when I start the program, I get the error

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'

which I don't understand because I have the data initialized.

The QObject.connect() function expects a callable argument. In writing btn.clicked.connect(plotCan.plot(self.data)) you are passing it the result of the call to plotCan.plot(self.data) ( None by default since no return is specified), hence the error message you are receiving

Since you want to pass the self.data variable along with the call, a simple way is to use a lambda

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

This satisfies the connect() function, and defers the call to plotCan.plot()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM