PyQt / Matplotlib: How to redraw / update a 3D surface plot in a window?

PyQt / Matplotlib: How to redraw / update a 3D surface plot in a window?



While executing the PyQt program the updated figure is plotting over the first plot.I want the plot to be appeared in a Window which is shown in a QWidget.The following idea works for the 3D line as well as point plots but not for the surface plots.


# imports

import sys
from PyQt4.QtCore import * # Python Qt4 bindings for GUI objects
from PyQt4.QtGui import *
from math import * # For fun log()
import numpy as np
from matplotlib.figure import Figure # For Matplotlib Figure Object
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg
import FigureCanvasQTAgg as FigureCanvas
from mpl_toolkits.mplot3d import Axes3D

class ThreeDSurface_GraphWindow(FigureCanvas): #Class for 3D window
def __init__(self):
self.fig =plt.figure(figsize=(7,7))
FigureCanvas.__init__(self, self.fig) #creating FigureCanvas
self.axes = self.fig.gca(projection='3d')#generates 3D Axes object
self.axes.hold(False)#clear axes on each run
self.setWindowTitle("Main") # sets Window title

def DrawGraph(self, x, y, z):#Fun for Graph plotting
self.axes.plot_surface(x, y, z) #plots the 3D surface plot
self.draw()
class TabConfigWidget(QWidget):# The QWidget in which the 3D window is been embedded
def __init__(self, parent=None):
super(TabConfigWidget, self).__init__(parent)
self.Combo=QComboBox()#ComboBox for change index
self.Combo.addItems(['Graph1','Graph2'])#add indexes to ComboBox
self.Combo.currentIndexChanged.connect(self.IndexChanged)#Invokes Fun IndexChanged when current index changes
self.ThreeDWin = ThreeDSurface_GraphWindow()#creating 3D Window
MainLayout = QGridLayout()# Layout for Main Tab Widget
MainLayout.setRowMinimumHeight(0, 5) #setting layout parameters
MainLayout.setRowMinimumHeight(2, 10)
MainLayout.setRowMinimumHeight(4, 5)
MainLayout.addWidget(self.Combo, 1, 1)#add GroupBox to Main layout
MainLayout.addWidget(self.ThreeDWin,2,1)#add 3D Window to Main layout
self.setLayout(MainLayout) #sets Main layout
x=np.linspace(-6,6,30) #X coordinates
y=np.linspace(-6,6,30) #Y coordinates
X,Y=np.meshgrid(x,y) #Forming MeshGrid
Z=self.f(X,Y)
self.ThreeDWin.DrawGraph(X,Y,Z)#call Fun for Graph plot

def f(self,x,y):#For Generating Z coordinates
return np.sin(np.sqrt(x**2+y**2))

def IndexChanged(self):#Invoked when the ComboBox index changes
x = np.linspace(-2, 6, 40) #X coordinates
y = np.linspace(-2, 6, 40) #Y coordinates
X, Y = np.meshgrid(x, y) #Forming MeshGrid
Z = self.f(X, Y)
self.ThreeDWin.DrawGraph(X, Y, Z) #call Fun for Graph plot

class GSPP(QTabWidget): #This is the Main QTabWidget
def __init__(self, parent=None):
super(GSPP, self).__init__(parent)
self.tab1 = TabConfigWidget()
self.addTab(self.tab1, "Tab1 ") #adding the QWidget

def Refresh(self): #Fun to refresh
return

if __name__ == '__main__': #The Fun for Main()
app = QApplication(sys.argv)
Window = GSPP()
Window.setWindowTitle("Main")
qr = Window.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
Window.move(qr.topLeft())
Window.showMaximized()
app.processEvents()
sys.exit(app.exec_())






Please add a simple, complete and running example that shows your problem.

– Joe
Sep 18 '18 at 11:05






Feel free to store the old surface in some variable and remove it before plotting a new one.

– ImportanceOfBeingErnest
Sep 18 '18 at 17:53






@Joe Sir, I have added a running sample program...Please go through it and help me as soon as possible....

– Sreeletha
Sep 24 '18 at 7:07




1 Answer
1



You just need to clear the axes before plotting:


def DrawGraph(self, x, y, z):#Fun for Graph plotting
self.axes.clear() # <<<
self.axes.plot_surface(x, y, z) #plots the 3D surface plot



I also added some random numbers to make the update visible. This is the full code:


import sys
from PyQt4.QtCore import * # Python Qt4 bindings for GUI objects
from PyQt4.QtGui import *
from math import * # For fun log()
import numpy as np
from matplotlib.figure import Figure # For Matplotlib Figure Object
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from mpl_toolkits.mplot3d import Axes3D

class ThreeDSurface_GraphWindow(FigureCanvas): #Class for 3D window
def __init__(self):
self.fig =plt.figure(figsize=(7,7))
FigureCanvas.__init__(self, self.fig) #creating FigureCanvas
self.axes = self.fig.gca(projection='3d')#generates 3D Axes object
self.axes.hold(False)#clear axes on each run
self.setWindowTitle("Main") # sets Window title

def DrawGraph(self, x, y, z):#Fun for Graph plotting
self.axes.clear()
self.axes.plot_surface(x, y, z) #plots the 3D surface plot
self.draw()


class TabConfigWidget(QWidget):# The QWidget in which the 3D window is been embedded
def __init__(self, parent=None):
super(TabConfigWidget, self).__init__(parent)
self.Combo=QComboBox()#ComboBox for change index
self.Combo.addItems(['Graph1','Graph2'])#add indexes to ComboBox
self.Combo.currentIndexChanged.connect(self.IndexChanged)#Invokes Fun IndexChanged when current index changes
self.ThreeDWin = ThreeDSurface_GraphWindow()#creating 3D Window
MainLayout = QGridLayout()# Layout for Main Tab Widget
MainLayout.setRowMinimumHeight(0, 5) #setting layout parameters
MainLayout.setRowMinimumHeight(2, 10)
MainLayout.setRowMinimumHeight(4, 5)
MainLayout.addWidget(self.Combo, 1, 1)#add GroupBox to Main layout
MainLayout.addWidget(self.ThreeDWin,2,1)#add 3D Window to Main layout
self.setLayout(MainLayout) #sets Main layout
x=np.linspace(-6,6,30) #X coordinates
y=np.linspace(-6,6,30) #Y coordinates
X,Y=np.meshgrid(x,y) #Forming MeshGrid
Z=self.f(X,Y)
self.ThreeDWin.DrawGraph(X,Y,Z)#call Fun for Graph plot

def f(self,x,y):#For Generating Z coordinates
return np.sin(np.sqrt(x**2+y**2))

def IndexChanged(self):#Invoked when the ComboBox index changes
x = np.linspace(np.random.randint(-5,0), np.random.randint(5,10), 40) #X coordinates
y = np.linspace(np.random.randint(-5,0), np.random.randint(5,10), 40) #Y coordinates


X, Y = np.meshgrid(x, y) #Forming MeshGrid
Z = self.f(X, Y)
self.ThreeDWin.DrawGraph(X, Y, Z) #call Fun for Graph plot

class GSPP(QTabWidget): #This is the Main QTabWidget
def __init__(self, parent=None):
super(GSPP, self).__init__(parent)
self.tab1 = TabConfigWidget()
self.addTab(self.tab1, "Tab1 ") #adding the QWidget

def Refresh(self): #Fun to refresh
return

if __name__ == '__main__': #The Fun for Main()
app = QApplication(sys.argv)
Window = GSPP()
Window.setWindowTitle("Main")
qr = Window.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
Window.move(qr.topLeft())
Window.showMaximized()
app.processEvents()
sys.exit(app.exec_())






...it's working...Thank you so much sir...

– Sreeletha
Sep 27 '18 at 6:51






If you are happy with the answer please accept it by clicking the tick mark on the left.

– Joe
Sep 27 '18 at 20:03



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)