'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 |
|---|
