简体   繁体   中英

Matplotlib and PyQt5 Plotting Figure

Trying to plot a pie chart with python in PyQt5 and Matplotlib and I'm having some issues. I'm able to have a pie chart and the data I want to display in it, but I'm trying to update the chart if I feed it new data when I call a certain function.

mplvl is the widget name that I am adding the figure to.

Every time I call this function it just adds another subplot. I've tried clearing the plot, clearing the figure, but I cannot get it to just delete and redraw the figure. I think I'm confused at how Matplotlib truly works, but any help would be appreciated.

import datetime
import calendar as cal
import sys

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow, QMessageBox, QTableWidgetItem
from PyQt5.uic import loadUi

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as FigureCanvas)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        loadUi('main.ui', self)

        self.date_from.setDate(QtCore.QDate(c_date.year, c_date.month, 1))
        self.date_to.setDate(QtCore.QDate(c_date.year, c_date.month, cal.monthrange(c_date.year, c_date.month)[1]))

        self.date_from.dateChanged.connect(self.fcn_date_changed)
        self.date_to.dateChanged.connect(self.fcn_date_changed)


    def fcn_date_changed(self):
        print("from: " + self.date_from.text() + " to: " + self.date_to.text())

        labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
        sizes = [15, 30, 45, 10]

        fig = Figure()
        ax1 = fig.add_subplot(111)
        ax1.set_title('Percentage Spending by Category')
        ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=False, startangle=90)
        main.canvas = FigureCanvas(fig)
        main.mplvl.addWidget(main.canvas)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

Below is main.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>861</width>
    <height>611</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="btn_add_item">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>71</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string>Add Item</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btn_edit_item">
    <property name="geometry">
     <rect>
      <x>190</x>
      <y>540</y>
      <width>81</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Edit Item</string>
    </property>
   </widget>
   <widget class="QListWidget" name="recent_items">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>130</y>
      <width>351</width>
      <height>401</height>
     </rect>
    </property>
   </widget>
   <widget class="QLabel" name="lbl_recent_items">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>110</y>
      <width>251</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>Recent Items</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btn_delete_item">
    <property name="geometry">
     <rect>
      <x>280</x>
      <y>540</y>
      <width>81</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Delete Item</string>
    </property>
   </widget>
   <widget class="QWidget" name="mplwindow" native="true">
    <property name="geometry">
     <rect>
      <x>380</x>
      <y>130</y>
      <width>471</width>
      <height>401</height>
     </rect>
    </property>
    <property name="sizePolicy">
     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
      <horstretch>0</horstretch>
      <verstretch>0</verstretch>
     </sizepolicy>
    </property>
    <layout class="QVBoxLayout" name="mplvl"/>
   </widget>
   <widget class="QPushButton" name="btn_view_items">
    <property name="geometry">
     <rect>
      <x>280</x>
      <y>100</y>
      <width>81</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>View Items</string>
    </property>
   </widget>
   <widget class="QDateEdit" name="date_from">
    <property name="geometry">
     <rect>
      <x>110</x>
      <y>60</y>
      <width>110</width>
      <height>21</height>
     </rect>
    </property>
    <property name="calendarPopup">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QDateEdit" name="date_to">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>60</y>
      <width>110</width>
      <height>21</height>
     </rect>
    </property>
    <property name="calendarPopup">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QLabel" name="lbl_showing_items1">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>60</y>
      <width>101</width>
      <height>21</height>
     </rect>
    </property>
    <property name="text">
     <string>Showing items from: </string>
    </property>
   </widget>
   <widget class="QLabel" name="lbl_showing_items1_2">
    <property name="geometry">
     <rect>
      <x>230</x>
      <y>60</y>
      <width>21</width>
      <height>21</height>
     </rect>
    </property>
    <property name="text">
     <string>to:</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>861</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

The logic is to:

  • create a single AxesSubplot ,
  • clean it,
  • call the function that implements the plot (in your case pie( )) and
  • call draw() to paint it.
    # ...
    self.date_to.dateChanged.connect(self.fcn_date_changed)

    fig = Figure()
    self.canvas = FigureCanvas(fig)
    self.mplvl.addWidget(self.canvas)
    self.ax1 = fig.add_subplot(111)
    self.ax1.pie([])

def fcn_date_changed(self):
    self.ax1.clear()
    self.ax1.set_title("Percentage Spending by Category")
    print("from: " + self.date_from.text() + " to: " + self.date_to.text())
    labels = "Frogs", "Hogs", "Dogs", "Logs"
    sizes = [15, 30, 45, 10]
    self.ax1.pie(
        sizes, labels=labels, autopct="%1.1f%%", shadow=False, startangle=90
    )
    self.ax1.figure.canvas.draw()

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