连接Qslider和MatplotlibWidget

时间:2014-02-04 16:07:12

标签: python qslider

我是python的真正初学者,并尝试将qslider连接到matplotlibwidget。 这意味着如果我更改滑块的值,图表应该更改。似乎值正确变化,而图表保持不变。谁能告诉我如何将滑块的变化与图形连接起来?这是我到目前为止的算法:

# -*- 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_())

问候 克里斯托弗

1 个答案:

答案 0 :(得分:0)

好的,我已对代码进行了一些更改,以使其有效:

  1. 更改def plot(self, R, axes):
  2. 的功能定义def plot(self, R):
  3. self.plot(position, self.mpl.axes)上的电话Rout相应更改为self.plot(position)
  4. 通过以下方式更改上一个axes.plot(xtotal, ytotal, 'r')功能的最后一行plot

    self.mpl.axes.clear() #clear the previous plot
    self.mpl.axes.plot(xtotal, ytotal, 'r') #replot
    self.mpl.figure.canvas.draw() #redraw the canvas
    
  5. 说明:  首先,如果轴已经是self.mpl的属性并且易于访问,则无需将轴传递给绘图函数。其次,当你制作另一个图时,你需要清除前一个图并刷新画布。

    接下来所有代码都经过修改,以便于使用复制粘贴:

    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_())