问题
I am a real beginner in python and try to connect a qslider to a matplotlibwidget. That means if I change the value of the slider the graph should change. It seems that the value changes correctly, while the graph stays the same. Can anyone tell me how to connect the change of the slider with the graph? Here is my algorithm so far:
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 04 16:48:12 2014
@author: Christoph
"""
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
import numpy as np
import scipy.constants as const
import sys
rcParams['font.size'] = 9
class MatplotlibWidget(Canvas):
"""
MatplotlibWidget inherits PyQt4.QtGui.QWidget
and matplotlib.backend_bases.FigureCanvasBase
Options: option_name (default_value)
-------
parent (None): parent widget
title (''): figure title
xlabel (''): X-axis label
ylabel (''): Y-axis label
xlim (None): X-axis limits ([min, max])
ylim (None): Y-axis limits ([min, max])
xscale ('linear'): X-axis scale
yscale ('linear'): Y-axis scale
width (4): width in inches
height (3): height in inches
dpi (100): resolution in dpi
hold (False): if False, figure will be cleared each time plot is called
Widget attributes:
-----------------
figure: instance of matplotlib.figure.Figure
axes: figure axes
Example:
-------
self.widget = MatplotlibWidget(self, yscale='log', hold=True)
from numpy import linspace
x = linspace(-10, 10)
self.widget.axes.plot(x, x**2)
self.wdiget.axes.plot(x, x**3)
"""
def __init__(self, parent=None, title='', xlabel='', ylabel='',
xlim=None, ylim=None, xscale='linear', yscale='linear',
width=4, height=3, dpi=100, hold=False):
self.figure = Figure(figsize=(width, height), dpi=dpi)
self.axes = self.figure.add_subplot(111)
self.axes.set_title(title)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
if xscale is not None:
self.axes.set_xscale(xscale)
if yscale is not None:
self.axes.set_yscale(yscale)
if xlim is not None:
self.axes.set_xlim(*xlim)
if ylim is not None:
self.axes.set_ylim(*ylim)
self.axes.hold(hold)
Canvas.__init__(self, self.figure)
self.setParent(parent)
Canvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QtGui.QSize(w, h)
def minimumSizeHint(self):
return QtGui.QSize(10, 10)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Graphics Window
self.mpl = MatplotlibWidget(self, title='Graph',
xlabel='x',
ylabel='y',
hold=True)
self.mpl.setGeometry(0,0,1300,800)
self.setGeometry(0, 30, 1680, 800)
# Slider Resistance
title1=QtGui.QLabel(self)
title1.setText('R')
title1.move(1400,10)
self.value1=QtGui.QLabel(self)
self.value1.setText('1')
self.value1.move(1550,40)
cb=QtGui.QSlider(QtCore.Qt.Horizontal, self)
cb.setGeometry(1400,40,100,30)
cb.setMinimum(1)
cb.setMaximum(10000)
cb.valueChanged.connect(self.Rout)
self.plot(1, self.mpl.axes)
def Rout(self, position):
self.value1.setText('%i' %position)
self.plot(position, self.mpl.axes)
def plot(self, R, axes):
x=np.linspace(0,5,1001)
B=0.035
n1=0.115
H=2.06227451e-15
n2=1.37040209e-01
gamma=0.001*const.e
C=0.13
x=np.array(x)
diodetheo = H*(np.exp((const.e*x*n2)/(const.k*300))-1)
zaehler = 1+np.exp((B-C+n1*x)*const.e/(const.k*300))
nenner = 1+np.exp((B-C-n1*x)*const.e/(const.k*300))
A=8.7476434*10**(29)*gamma
D=gamma/2
klammer2 = (const.pi/2)+np.arctan((C-n1*x)/D)
y1 = A*np.log(zaehler/nenner)*klammer2
# plt.figure()
# plt.plot(x, diodetheo, 'g')
# plt.show()
indup=[]
inddown=[]
iup=[]
idown=[]
theo = (y1+diodetheo)*(10**(-12))*(100)/4
for i, Volt in enumerate(x):
xup=np.linspace(0,Volt,i+1)
last=Volt/R-xup/R
diff=np.array(last)-np.array(theo[0:i+1])
inter=np.where(np.diff(np.sign(diff)))[0]
if inter.size==0:
inter=np.array([0])
indup.append(inter[0])
inddown.append(inter[-1])
iup.append(theo[inter[0]])
idown.append(theo[inter[-1]])
up = np.array(iup)
down = np.array(idown)
down=np.flipud(down)
ytotal=np.concatenate((up, down))
xneg=np.flipud(x)
xtotal=np.concatenate((x,xneg))
#plt.figure()
#plt.plot(xtotal, ytotal, 'g')
#plt.show()
axes.plot(xtotal, ytotal, 'r')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = ApplicationWindow()
win.show()
sys.exit(app.exec_())
Greetings Christoph
回答1:
OK I've made some changes to your code in order to make it works:
- Change the function definition
def plot(self, R, axes):
fordef plot(self, R):
- Change the call
self.plot(position, self.mpl.axes)
onRout
accordingly toself.plot(position)
Change the final line
axes.plot(xtotal, ytotal, 'r')
on the previousplot
function by:self.mpl.axes.clear() #clear the previous plot self.mpl.axes.plot(xtotal, ytotal, 'r') #replot self.mpl.figure.canvas.draw() #redraw the canvas
Explanations:
First, you don't need to pass the axes to the plot function if it's already an attribute of self.mpl
and is easy accessible. Second, when you make another plot you need to clear the previous one and also refresh the canvas.
Next all the code with modifications for easy use of copy-paste:
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
import numpy as np
import scipy.constants as const
import sys
rcParams['font.size'] = 9
class MatplotlibWidget(Canvas):
"""
MatplotlibWidget inherits PyQt4.QtGui.QWidget
and matplotlib.backend_bases.FigureCanvasBase
Options: option_name (default_value)
-------
parent (None): parent widget
title (''): figure title
xlabel (''): X-axis label
ylabel (''): Y-axis label
xlim (None): X-axis limits ([min, max])
ylim (None): Y-axis limits ([min, max])
xscale ('linear'): X-axis scale
yscale ('linear'): Y-axis scale
width (4): width in inches
height (3): height in inches
dpi (100): resolution in dpi
hold (False): if False, figure will be cleared each time plot is called
Widget attributes:
-----------------
figure: instance of matplotlib.figure.Figure
axes: figure axes
Example:
-------
self.widget = MatplotlibWidget(self, yscale='log', hold=True)
from numpy import linspace
x = linspace(-10, 10)
self.widget.axes.plot(x, x**2)
self.wdiget.axes.plot(x, x**3)
"""
def __init__(self, parent=None, title='', xlabel='', ylabel='',
xlim=None, ylim=None, xscale='linear', yscale='linear',
width=4, height=3, dpi=100, hold=False):
self.figure = Figure(figsize=(width, height), dpi=dpi)
self.axes = self.figure.add_subplot(111)
self.axes.set_title(title)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
if xscale is not None:
self.axes.set_xscale(xscale)
if yscale is not None:
self.axes.set_yscale(yscale)
if xlim is not None:
self.axes.set_xlim(*xlim)
if ylim is not None:
self.axes.set_ylim(*ylim)
self.axes.hold(hold)
Canvas.__init__(self, self.figure)
self.setParent(parent)
Canvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QtGui.QSize(w, h)
def minimumSizeHint(self):
return QtGui.QSize(10, 10)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Graphics Window
self.mpl = MatplotlibWidget(self, title='Graph',
xlabel='x',
ylabel='y',
hold=True)
self.mpl.setGeometry(0,0,1300,800)
self.setGeometry(0, 30, 1680, 800)
# Slider Resistance
title1=QtGui.QLabel(self)
title1.setText('R')
title1.move(1400,10)
self.value1=QtGui.QLabel(self)
self.value1.setText('1')
self.value1.move(1550,40)
cb=QtGui.QSlider(QtCore.Qt.Horizontal, self)
cb.setGeometry(1400,40,100,30)
cb.setMinimum(1)
cb.setMaximum(10000)
cb.valueChanged.connect(self.Rout)
self.plot(1)
def Rout(self, position):
self.value1.setText('%i' %position)
self.plot(position)
def plot(self, R):
x=np.linspace(0,5,1001)
B=0.035
n1=0.115
H=2.06227451e-15
n2=1.37040209e-01
gamma=0.001*const.e
C=0.13
x=np.array(x)
diodetheo = H*(np.exp((const.e*x*n2)/(const.k*300))-1)
zaehler = 1+np.exp((B-C+n1*x)*const.e/(const.k*300))
nenner = 1+np.exp((B-C-n1*x)*const.e/(const.k*300))
A=8.7476434*10**(29)*gamma
D=gamma/2
klammer2 = (const.pi/2)+np.arctan((C-n1*x)/D)
y1 = A*np.log(zaehler/nenner)*klammer2
# plt.figure()
# plt.plot(x, diodetheo, 'g')
# plt.show()
indup=[]
inddown=[]
iup=[]
idown=[]
theo = (y1+diodetheo)*(10**(-12))*(100)/4
for i, Volt in enumerate(x):
xup=np.linspace(0,Volt,i+1)
last=Volt/R-xup/R
diff=np.array(last)-np.array(theo[0:i+1])
inter=np.where(np.diff(np.sign(diff)))[0]
if inter.size==0:
inter=np.array([0])
indup.append(inter[0])
inddown.append(inter[-1])
iup.append(theo[inter[0]])
idown.append(theo[inter[-1]])
up = np.array(iup)
down = np.array(idown)
down=np.flipud(down)
ytotal=np.concatenate((up, down))
xneg=np.flipud(x)
xtotal=np.concatenate((x,xneg))
#plt.figure()
#plt.plot(xtotal, ytotal, 'g')
#plt.show()
self.mpl.axes.clear()
self.mpl.axes.plot(xtotal, ytotal, 'r')
self.mpl.figure.canvas.draw()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = ApplicationWindow()
win.show()
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/21557425/connect-qslider-and-matplotlibwidget