'how to update fig in matplotlib embedded in PyQt5?

I use a QComboBox to provide multiple choices. When a user change the choice, I obtain the currentText of the QComboBox. Then find the matched variable in the dataset, and make a boxplot and show the boxplot in a QWidget. When the choice is changed, the boxplot should be changed. However, the boxplot cannot be updated in the QWidget.

Following is the Stack.ui file.

<?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>1318</width>
    <height>844</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout_5">
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
       <number>0</number>
      </property>
      <widget class="QWidget" name="tabDescrip">
       <attribute name="title">
        <string>Descriptive statistical analysis</string>
       </attribute>
       <layout class="QVBoxLayout" name="verticalLayout_4">
        <item>
         <layout class="QHBoxLayout" name="horizontalLayout_4">
          <item>
           <layout class="QVBoxLayout" name="verticalLayout_2">
            <item>
             <layout class="QHBoxLayout" name="horizontalLayout">
              <item>
               <widget class="QLabel" name="labelType">
                <property name="text">
                 <string>Property types</string>
                </property>
               </widget>
              </item>
              <item>
               <widget class="QComboBox" name="comboBoxType">
                <item>
                 <property name="text">
                  <string>Rock properties</string>
                 </property>
                </item>
                <item>
                 <property name="text">
                  <string>Oil properties</string>
                 </property>
                </item>
               </widget>
              </item>
             </layout>
            </item>
            <item>
             <layout class="QHBoxLayout" name="horizontalLayout_2">
              <item>
               <widget class="QLabel" name="labelName">
                <property name="text">
                 <string>Property name</string>
                </property>
               </widget>
              </item>
              <item>
               <widget class="QComboBox" name="comboBoxName"/>
              </item>
             </layout>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QVBoxLayout" name="verticalLayout_3">
            <item>
             <widget class="QPushButton" name="buttonPlot">
              <property name="text">
               <string>Plot</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QWidget" name="contentPlot" native="true">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="autoFillBackground">
               <bool>true</bool>
              </property>
             </widget>
            </item>
           </layout>
          </item>
         </layout>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1318</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Following is the codes.

from __future__ import division
from PyQt5 import QtWidgets, uic
from PyQt5.QtWidgets import QTableWidgetItem, QApplication
import pandas as pd
import numpy as np
import matplotlib
matplotlib.use('QT5Agg')
import matplotlib.pylab as plt
from matplotlib.backends.backend_qt5agg import FigureCanvas

# load ui file
gui_file = 'Stack.ui'
[Ui_MainWindow, QtBaseClass] = uic.loadUiType(gui_file)

# create dataset
permeability = [4, 4, 2, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5]
porosity = [45, 45, 44.8, 46.5, 44.9, 45.7, 45, 44.7, 43.7, 46.5, 44.9, 43.5, 44.4, 43.4, 44.7, 44.7, 43.4, 44.7, 44.7]
temperature = [25, 25, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40]
oil_gravity = [47.61, 47.61, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69, 41.69]
acid_number = [1.10, 3.4, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04, 1.04]

d = {'permeability': permeability,
        'porosity': porosity,
        'temperature': temperature,
        'oil gravity': oil_gravity,
        'acid number': acid_number
     }
df = pd.DataFrame(d)
global DF_global
DF_global = df

# define a class
class MainBody(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)

        # check property types change
        self.comboBoxType.currentIndexChanged.connect(self.PropertyName)

        # set initial property name
        propertyType = self.comboBoxType.currentText()
        if propertyType == 'Rock properties':
            self.comboBoxName.clear()
            self.comboBoxName.addItems(['porosity', 'permeability', 'temperature'])

        # click the button to make a plot
        self.buttonPlot.clicked.connect(self.DescripPlot)


    # set property name when property types are changed
    def PropertyName(self):
        propertyType = self.comboBoxType.currentText()
        if propertyType == 'Rock properties':
            self.comboBoxName.clear()
            self.comboBoxName.addItems(['porosity', 'permeability', 'temperature'])
        else:
            self.comboBoxName.clear()
            self.comboBoxName.addItems(['oil gravity', 'acid number'])

   # descriptive plot
    def DescripPlot(self):
        # obtain current choice
        PropertyName_chosen = self.comboBoxName.currentText()
        # find the matched variable in imported dataset, the dataset is imported in other function
        array_col = DF_global[PropertyName_chosen].to_numpy()
        # remove nan from array to make plot
        filtered_array_col = array_col[~np.isnan(array_col)]

        # make a boxplot
        fig, ax = plt.subplots(1, 1)
        ax.boxplot(filtered_array_col)

        # put plot on QtWidgets
        self.plotWidget = FigureCanvas(fig)
        lay = QtWidgets.QVBoxLayout(self.contentPlot)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.plotWidget)

app = QApplication([])
first = MainBody()
first.show()
app.exec_()


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source