View  Edit  Attributes  History  Attach  Print  Search

PYQTLAB

PyQt Lab' : Graphiques Math : Pyqtgraph : Affichage progressif d'une courbe dans un graphique Pyqtgraph avec bouton de Stop, bouton Effacer, bouton réglage vitesse et lcdNumber d'affichage.

Par X. HINAULT - Juin 2013

Ce que l'on va faire ici

  • Affichage progressif d'une courbe dans un graphique Pyqtgraph avec bouton de Stop, bouton Effacer, bouton réglage vitesse et lcdNumber d'affichage.

Pré-requis

  • python 2.7
  • pyqt4.x
  • pyqtgraph

Le fichier d'interface *.ui


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>658</width>
    <height>413</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>PyQt + pyqtgraph : Affichage courbe progressive avec stop, lcdNumber</string>
  </property>
  <widget class="PlotWidget" name="graph">
   <property name="geometry">
    <rect>
     <x>5</x>
     <y>10</y>
     <width>480</width>
     <height>360</height>
    </rect>
   </property>
  </widget>
  <widget class="QLineEdit" name="lineEditValeurMin">
   <property name="geometry">
    <rect>
     <x>500</x>
     <y>80</y>
     <width>66</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>-1000</string>
   </property>
  </widget>
  <widget class="QLabel" name="labelUnite">
   <property name="geometry">
    <rect>
     <x>595</x>
     <y>130</y>
     <width>51</width>
     <height>13</height>
    </rect>
   </property>
   <property name="text">
    <string>Unité :</string>
   </property>
  </widget>
  <widget class="QLCDNumber" name="lcdNumberValeurBrute">
   <property name="geometry">
    <rect>
     <x>495</x>
     <y>25</y>
     <width>96</width>
     <height>36</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true">background-color: rgb(170, 255, 127);
color: rgb(0, 170, 0);</string>
   </property>
   <property name="smallDecimalPoint">
    <bool>false</bool>
   </property>
  </widget>
  <widget class="QLabel" name="labelValeurCalc">
   <property name="geometry">
    <rect>
     <x>500</x>
     <y>110</y>
     <width>106</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>Valeur calculée :</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="lineEditValeurMax">
   <property name="geometry">
    <rect>
     <x>575</x>
     <y>80</y>
     <width>66</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>+1000</string>
   </property>
  </widget>
  <widget class="QLabel" name="labelDelaiMesure">
   <property name="geometry">
    <rect>
     <x>510</x>
     <y>265</y>
     <width>71</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>delai ms</string>
   </property>
  </widget>
  <widget class="QLabel" name="labelValeurBrute">
   <property name="geometry">
    <rect>
     <x>495</x>
     <y>10</y>
     <width>81</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>Valeur brute :</string>
   </property>
  </widget>
  <widget class="QLabel" name="labelValeurMin">
   <property name="geometry">
    <rect>
     <x>500</x>
     <y>65</y>
     <width>71</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>Valeur mini</string>
   </property>
  </widget>
  <widget class="QLCDNumber" name="lcdNumberValeurCalc">
   <property name="geometry">
    <rect>
     <x>495</x>
     <y>130</y>
     <width>96</width>
     <height>36</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true">background-color: rgb(255, 255, 0);
color: rgb(255, 0, 0);</string>
   </property>
   <property name="smallDecimalPoint">
    <bool>true</bool>
   </property>
   <property name="mode">
    <enum>QLCDNumber::Dec</enum>
   </property>
  </widget>
  <widget class="QDial" name="dialDelaiMesure">
   <property name="geometry">
    <rect>
     <x>505</x>
     <y>175</y>
     <width>50</width>
     <height>64</height>
    </rect>
   </property>
   <property name="minimum">
    <number>0</number>
   </property>
   <property name="maximum">
    <number>8</number>
   </property>
   <property name="value">
    <number>4</number>
   </property>
   <property name="notchesVisible">
    <bool>true</bool>
   </property>
  </widget>
  <widget class="QPushButton" name="pushRadioButtonStop">
   <property name="geometry">
    <rect>
     <x>575</x>
     <y>240</y>
     <width>66</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>STOP</string>
   </property>
   <property name="checkable">
    <bool>true</bool>
   </property>
  </widget>
  <widget class="QLabel" name="labelValeurMax">
   <property name="geometry">
    <rect>
     <x>575</x>
     <y>65</y>
     <width>71</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>Valeur maxi</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="lineEditUnite">
   <property name="geometry">
    <rect>
     <x>595</x>
     <y>145</y>
     <width>56</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>U</string>
   </property>
  </widget>
  <widget class="QLCDNumber" name="lcdNumberDelaiMesure">
   <property name="geometry">
    <rect>
     <x>500</x>
     <y>240</y>
     <width>64</width>
     <height>23</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true">background-color: rgb(255, 255, 147);
color: rgb(0, 85, 255);</string>
   </property>
   <property name="midLineWidth">
    <number>0</number>
   </property>
   <property name="segmentStyle">
    <enum>QLCDNumber::Flat</enum>
   </property>
   <property name="value" stdset="0">
    <double>0.000000000000000</double>
   </property>
  </widget>
  <widget class="QPushButton" name="pushButtonEffacer">
   <property name="geometry">
    <rect>
     <x>575</x>
     <y>195</y>
     <width>66</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>Effacer</string>
   </property>
  </widget>
 </widget>
 <customwidgets>
  <customwidget>
   <class>PlotWidget</class>
   <extends>QGraphicsView</extends>
   <header>pyqtgraph</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

 

Le fichier d'interface *.py

  • Fichier obtenu automatiquement avec l'utilitaire pyuic4 à partir du fichier *.ui créé avec QtDesigner :
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file
#
# Created: Sun Aug 18 15:02:46 2013
#      by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(658, 413)
        self.graph = PlotWidget(Form)
        self.graph.setGeometry(QtCore.QRect(5, 10, 480, 360))
        self.graph.setObjectName(_fromUtf8("graph"))
        self.lineEditValeurMin = QtGui.QLineEdit(Form)
        self.lineEditValeurMin.setGeometry(QtCore.QRect(500, 80, 66, 23))
        self.lineEditValeurMin.setObjectName(_fromUtf8("lineEditValeurMin"))
        self.labelUnite = QtGui.QLabel(Form)
        self.labelUnite.setGeometry(QtCore.QRect(595, 130, 51, 13))
        self.labelUnite.setObjectName(_fromUtf8("labelUnite"))
        self.lcdNumberValeurBrute = QtGui.QLCDNumber(Form)
        self.lcdNumberValeurBrute.setGeometry(QtCore.QRect(495, 25, 96, 36))
        self.lcdNumberValeurBrute.setStyleSheet(_fromUtf8("background-color: rgb(170, 255, 127);\n"
"color: rgb(0, 170, 0);"))
        self.lcdNumberValeurBrute.setSmallDecimalPoint(False)
        self.lcdNumberValeurBrute.setObjectName(_fromUtf8("lcdNumberValeurBrute"))
        self.labelValeurCalc = QtGui.QLabel(Form)
        self.labelValeurCalc.setGeometry(QtCore.QRect(500, 110, 106, 16))
        self.labelValeurCalc.setObjectName(_fromUtf8("labelValeurCalc"))
        self.lineEditValeurMax = QtGui.QLineEdit(Form)
        self.lineEditValeurMax.setGeometry(QtCore.QRect(575, 80, 66, 23))
        self.lineEditValeurMax.setObjectName(_fromUtf8("lineEditValeurMax"))
        self.labelDelaiMesure = QtGui.QLabel(Form)
        self.labelDelaiMesure.setGeometry(QtCore.QRect(510, 265, 71, 16))
        self.labelDelaiMesure.setObjectName(_fromUtf8("labelDelaiMesure"))
        self.labelValeurBrute = QtGui.QLabel(Form)
        self.labelValeurBrute.setGeometry(QtCore.QRect(495, 10, 81, 16))
        self.labelValeurBrute.setObjectName(_fromUtf8("labelValeurBrute"))
        self.labelValeurMin = QtGui.QLabel(Form)
        self.labelValeurMin.setGeometry(QtCore.QRect(500, 65, 71, 16))
        self.labelValeurMin.setObjectName(_fromUtf8("labelValeurMin"))
        self.lcdNumberValeurCalc = QtGui.QLCDNumber(Form)
        self.lcdNumberValeurCalc.setGeometry(QtCore.QRect(495, 130, 96, 36))
        self.lcdNumberValeurCalc.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 0);\n"
"color: rgb(255, 0, 0);"))
        self.lcdNumberValeurCalc.setSmallDecimalPoint(True)
        self.lcdNumberValeurCalc.setMode(QtGui.QLCDNumber.Dec)
        self.lcdNumberValeurCalc.setObjectName(_fromUtf8("lcdNumberValeurCalc"))
        self.dialDelaiMesure = QtGui.QDial(Form)
        self.dialDelaiMesure.setGeometry(QtCore.QRect(505, 175, 50, 64))
        self.dialDelaiMesure.setMinimum(0)
        self.dialDelaiMesure.setMaximum(8)
        self.dialDelaiMesure.setProperty("value", 4)
        self.dialDelaiMesure.setNotchesVisible(True)
        self.dialDelaiMesure.setObjectName(_fromUtf8("dialDelaiMesure"))
        self.pushRadioButtonStop = QtGui.QPushButton(Form)
        self.pushRadioButtonStop.setGeometry(QtCore.QRect(575, 240, 66, 27))
        self.pushRadioButtonStop.setCheckable(True)
        self.pushRadioButtonStop.setObjectName(_fromUtf8("pushRadioButtonStop"))
        self.labelValeurMax = QtGui.QLabel(Form)
        self.labelValeurMax.setGeometry(QtCore.QRect(575, 65, 71, 16))
        self.labelValeurMax.setObjectName(_fromUtf8("labelValeurMax"))
        self.lineEditUnite = QtGui.QLineEdit(Form)
        self.lineEditUnite.setGeometry(QtCore.QRect(595, 145, 56, 23))
        self.lineEditUnite.setObjectName(_fromUtf8("lineEditUnite"))
        self.lcdNumberDelaiMesure = QtGui.QLCDNumber(Form)
        self.lcdNumberDelaiMesure.setGeometry(QtCore.QRect(500, 240, 64, 23))
        self.lcdNumberDelaiMesure.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 147);\n"
"color: rgb(0, 85, 255);"))
        self.lcdNumberDelaiMesure.setMidLineWidth(0)
        self.lcdNumberDelaiMesure.setSegmentStyle(QtGui.QLCDNumber.Flat)
        self.lcdNumberDelaiMesure.setProperty("value", 0.0)
        self.lcdNumberDelaiMesure.setObjectName(_fromUtf8("lcdNumberDelaiMesure"))
        self.pushButtonEffacer = QtGui.QPushButton(Form)
        self.pushButtonEffacer.setGeometry(QtCore.QRect(575, 195, 66, 27))
        self.pushButtonEffacer.setObjectName(_fromUtf8("pushButtonEffacer"))

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "PyQt + pyqtgraph : Affichage courbe progressive avec stop, lcdNumber", None, QtGui.QApplication.UnicodeUTF8))
        self.lineEditValeurMin.setText(QtGui.QApplication.translate("Form", "-1000", None, QtGui.QApplication.UnicodeUTF8))
        self.labelUnite.setText(QtGui.QApplication.translate("Form", "Unité :", None, QtGui.QApplication.UnicodeUTF8))
        self.labelValeurCalc.setText(QtGui.QApplication.translate("Form", "Valeur calculée :", None, QtGui.QApplication.UnicodeUTF8))
        self.lineEditValeurMax.setText(QtGui.QApplication.translate("Form", "+1000", None, QtGui.QApplication.UnicodeUTF8))
        self.labelDelaiMesure.setText(QtGui.QApplication.translate("Form", "delai ms", None, QtGui.QApplication.UnicodeUTF8))
        self.labelValeurBrute.setText(QtGui.QApplication.translate("Form", "Valeur brute :", None, QtGui.QApplication.UnicodeUTF8))
        self.labelValeurMin.setText(QtGui.QApplication.translate("Form", "Valeur mini", None, QtGui.QApplication.UnicodeUTF8))
        self.pushRadioButtonStop.setText(QtGui.QApplication.translate("Form", "STOP", None, QtGui.QApplication.UnicodeUTF8))
        self.labelValeurMax.setText(QtGui.QApplication.translate("Form", "Valeur maxi", None, QtGui.QApplication.UnicodeUTF8))
        self.lineEditUnite.setText(QtGui.QApplication.translate("Form", "U", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButtonEffacer.setText(QtGui.QApplication.translate("Form", "Effacer", None, QtGui.QApplication.UnicodeUTF8))

from pyqtgraph import PlotWidget

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
 

Le fichier d'application *Main.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

# par X. HINAULT - Mai 2013 - Tous droits réservés
# GPLv3 - www.mon-club-elec.fr

# modules a importer
from PyQt4.QtGui import *
from PyQt4.QtCore import *  # inclut QTimer..
import os,sys

import pyqtgraph as pg # pour accès à certaines constantes pyqtgraph, widget, etc...

import numpy as np # math et tableaux

from tuto_pyqt_pyqtgraph_timer_courbe_effacer_stop_vitesse import * # fichier obtenu à partir QtDesigner et pyuic4

# +/- variables et objets globaux

class myApp(QWidget, Ui_Form): # la classe reçoit le Qwidget principal ET la classe définie dans test.py obtenu avec pyuic4
        def __init__(self, parent=None):
                QWidget.__init__(self) # initialise le Qwidget principal
                self.setupUi(parent) # Obligatoire

                # --- Variables de classe
                # --- Paramétrage des widgets de l'interface GUI si nécessaire ---

                # --- Connexions entre signaux des widgets et fonctions
                # connecte chaque signal utilisé des objets à l'appel de la fonction voulue

                self.connect(self.pushButtonEffacer, SIGNAL("clicked()"), self.pushButtonEffacerClicked) # connecte le signal Clicked de l'objet bouton à l'appel de la fonction voulue

                self.connect(self.pushRadioButtonStop, SIGNAL("clicked()"), self.pushRadioButtonStopClicked) # connecte le signal Clicked de l'objet bouton à l'appel de la fonction voulue

                self.connect(self.dialDelaiMesure, SIGNAL("valueChanged(int)"), self.dialDelaiMesureChanged) # connecte le signal Clicked de l'objet bouton à l'appel de la fonction voulue

                self.pushRadioButtonStop.setStyleSheet(QString.fromUtf8("background-color: rgb(0, 255, 0);")) # bouton de stop en vert au depart

                #-- pour délais de mesure en ms
                self.delaisMesure=[1,2,4,8,16,32,64,128,256] # en ms
                self.interval=self.delaisMesure[4] # intervalle entre  2 valeurs - en ms
                self.lcdNumberDelaiMesure.display(self.delaisMesure[4]) # valeur initiale pour le délai

                # --- Code actif initial  ---

                #-- initialise le graphique pyqtgraph --
                # l'objet self.graph correspond au plotWidget créé dans QtDesigner

                # aspect fond /axes
                #self.graph.hideAxis('left') # masque axes - ‘left’, ‘bottom’, ‘right’, or ‘top’               
                self.graph.setBackgroundBrush(QBrush(QColor(Qt.white))) # la classe PlotWidget est un GraphicsWidget qui est un QGraphics View
                self.graph.showGrid(x=True, y=True)  # affiche la grille
                self.graph.getAxis('bottom').setPen(pg.mkPen(0,0,255)) # couleur de l'axe + grille
                self.graph.getAxis('left').setPen(pg.mkPen(255,0,0)) # couleur de l'axe + grille

                # légende des axes
                labelStyle = {'color': '#00F', 'font-size': '10pt'} # propriétés CSS à utiliser pour le label
                self.graph.getAxis('bottom').setLabel('X', units='unit', **labelStyle) # label de l'axe
                self.graph.getAxis('left').setLabel('Y', units='unit', **labelStyle) # label de l'axe

                # adaptation échelle axes
                # axe X et Y sont autoscale par défaut
                self.graph.enableAutoRange(axis=pg.ViewBox.YAxis, enable=False) # fonction plotItem : désactive autoscale Y

                self.Ymin=-1
                self.Ymax=1            
                self.graph.setYRange(self.Ymin,self.Ymax) # fonction plotItem : fixe échelle des Y

                self.Xmin=0
                self.Xmax=360  
                self.graph.setXRange(self.Xmin,self.Xmax) # fonction plotItem : fixe échelle des X

                # interactivité
                #self.graph.setInteractive(False) # fonction QGraphics View : pour inactiver interaction souris
                self.graph.getViewBox().setMouseMode(pg.ViewBox.RectMode)  # fonction ViewBox pas accessible depuis PlotWidget : fixe selection par zone
                self.graph.setMouseEnabled(x=False, y=True) # désactive interactivité axe X

                #-- initialise données --
                #-- définition des x
                #self.nombreValeurs=360
                #self.x = np.arange(0.0, self.nombreValeurs+1, 1.0) # crée un vecteur de n valeurs à intervalle régulier pour les x
                #print(self.x) # debug - affiche les valeurs x

                #-- calcul des y : courbe y=f(x)
                #self.y=np.sin(np.radians(self.x))# crée un tableau de valeur y basé sur x - courbe y=sin(x)
                #self.y= np.random.normal(0,1,size=self.nombreValeurs) # génére une série de 1000 valeurs aléatoires

                #print(self.y) # debug - affiche les valeurs y

                #-- affichage de la courbe --
                self.courbe=self.graph.plot(pen=(0,0,255)) # avec couleur

                self.compt=0 # variable comptage

                #-- initialisation du Timer
                self.timer=QTimer() # déclare un timer Qt
                self.timer.start(self.interval) # lance le timer - durée en ms
                self.connect(self.timer, SIGNAL("timeout()"), self.timerEvent) # connecte le signal timeOut de l'objet timer à l'appel de la fonction voulue
                # NB : le nom de la fonction appelée est ici timerEvent : ce nom est arbitraire et peut être ce que l'on veut...


        # --- les fonctions appelées, utilisées par les signaux des widgets ---

        #--- si modif delai mesure --
        def dialDelaiMesureChanged(self, valeur):
                print("Dial Delai Mesure modifié : " + str(valeur) + " | délai = " + str(self.delaisMesure[valeur]) + " ms")
                self.lcdNumberDelaiMesure.display(self.delaisMesure[valeur]) # utilise la valeur [i] pour le délai

                self.interval=self.delaisMesure[valeur]
                self.timer.setInterval(self.interval) # modifie le nouvel intervalle du timer

                if self.pushRadioButtonStop.isChecked()is not True: # si le bouton stop est pas enfoncé
                        self.timer.start() # redémarre le timer


        #---- bouton STOP -------
        def pushRadioButtonStopClicked(self):
                print("Bouton Stop appuyé")
                print("Etat bouton Stop =" + str(self.pushRadioButtonStop.isChecked()))
                if self.pushRadioButtonStop.isChecked(): # si bouton enfoncé
                        self.pushRadioButtonStop.setStyleSheet(QString.fromUtf8("background-color: rgb(255, 0, 0);"))
                        self.timer.stop() # stop le timer
                else:
                        self.pushRadioButtonStop.setStyleSheet(QString.fromUtf8("background-color: rgb(0, 255, 0);"))
                        self.timer.start() # redémarre le timer

        #--- bouton effacer --
        def pushButtonEffacerClicked(self):
                print("Bouton Effacer cliqué")
                #self.timer.stop() # arret timer
                self.compt=0 # réinitialise comptage valeurs et donc graphique...
                self.timerEvent() # appelle la fonction timerEvent pour prise en compte immédiate

        # --- les fonctions appelées, utilisées par les signaux hors widgets ---

        #-- fonction gestion survenue évènement Timer
        def timerEvent(self): # fonction appelée lors de la survenue d'un évènement Timer - nom de la fonction indiférrent
                #print("Timer")

                if self.compt==0: # premier passage
                        self.points= np.array([[self.compt,self.compt]]) # tableau à 2 dimensions - ici 1er points
                        newY=np.sin(np.radians(self.compt)) * np.cos(np.radians(3*self.compt))
                        self.x=self.points[:,0] # la première colonne = les x
                        self.y=self.points[:,1] # la deuxième colonne = les y          
                        self.compt=self.compt+1 # incrémente compt
                elif self.compt<=self.Xmax: # on remplit le tableau de point une première fois
                        newY=np.sin(np.radians(self.compt)) * np.cos(np.radians(3*self.compt))
                        #newY=self.compt # x=y - debug
                        self.points=np.append(self.points,[[self.compt,newY]],axis=0)# ajouter un point au tableau
                        self.x=self.points[:,0] # la première colonne = les x
                        self.y=self.points[:,1] # la deuxième colonne = les y          
                        self.compt=self.compt+1 # incrémente compt
                else:
                        #self.points=roll(self.points,1, axis=1) # décale les éléments y de 1 - fonctin numpy
                        #self.x=self.points[:,0] # la première colonne = les x - existe déjà
                        #self.y=self.points[:,1] # la deuxième colonne = les y - existe déjà

                        #self.y=roll(self.y,1) # décale les éléments y de 1 - fonctin numpy - les x ne bougent pas..
                        self.y=np.roll(self.y,-1) # décale les éléments y de 1 - fonction numpy - les x ne bougent pas.. et remet y[0] en y[max].. évite recalcul...
                        newY=self.y[len(self.y)-1] # derniere valeur du tableau y
                        #self.y[self.Xmax-1]=self.y[self.Xmax-1]/2 # nouvelle valeur en dernière position
                        #self.y[self.Xmax]=0 # nouvelle valeur en dernière position
                        #self.y[self.Xmax]=np.sin(np.radians(self.compt)) * np.cos(np.radians(3*self.compt)) # avec recalcul
                        #self.compt=self.compt+1 # incrémente compt

                        # important : pour le tracé, ce n'est pas l'ordre qui est important, mais la coordonnée x,y dans notre cas...

                # remarquer la simplicité avec laquelle il es possible d'extraire le tableau des x ou des y à partir du tableau de points


                #if self.compt==self.Xmax : self.compt=0 # RAZ compt

                # debug
                #print self.points
                #print self.x  
                #print self.y

                """
                #-- initialise données --
                self.x = arange(0.0, 361.0, 1.0) # crée un vecteur de n valeurs à intervalle régulier pour les x
                print(self.x) # debug - affiche les valeurs x

                #self.y = zeros(len(self.x), Float) # debug - crée un tableau rempli de 0 de la taille voulue pour les y       
                #-- calcul des y : courbe y=sin(x).cos(3x)
                self.y=sin(radians(self.x)) * cos(radians(3*self.x))# crée un tableau de valeur y basé sur x
                print(self.y) # debug - affiche les valeurs y
                """

                #-- met à jour leslcdNumber
                # actualise lcdNumber
                self.lcdNumberValeurBrute.display(newY) # affiche la valeur

                # équiv map : interp(256,[1,512],[5,10]) (package numpy)
                self.valeurCalc=np.interp(newY, [-1,1],[float(self.lineEditValeurMin.text()),float(self.lineEditValeurMax.text())]) # équiv map
                self.lcdNumberValeurCalc.display(self.valeurCalc)

                #-- initialise la courbe --
                self.courbe.setData(self.x,self.y) # initialisation valeurs courbe

        # --- fonctions de classes autres---    

# -- Autres Classes utiles --

# -- Classe principale (lancement)  --
def main(args):
        a=QApplication(args) # crée l'objet application
        f=QWidget() # crée le QWidget racine
        c=myApp(f) # appelle la classe contenant le code de l'application
        f.show() # affiche la fenêtre QWidget
        r=a.exec_() # lance l'exécution de l'application
        return r

if __name__=="__main__": # pour rendre le code exécutable
        main(sys.argv) # appelle la fonction main

 

Utilisation

  • Les 2 fichiers suivants sont à enregistrer dans un même répertoire, l'un en nom.py et l'autre en nomMain.py.
  • Puis lancer l'application depuis Geany ou équivalent, en exécutant le fichier nomMain.py
  • Le bouton de Stop arrêt de défilement, le bouton effacer, efface, le bouton rotatif assure le réglage de la vitesse de défilement.

Discussion technique

  • Il serait préférable de ne pas actualiser le graphique à la même fréquence que le calcul de valeur : si délai à 2ms, cela fait 500 calculs par seconde, et 500 rafraîchissement. On peut imaginer plutôt de rafraîchir que toutes les 33 ms (=30 fps) tout en faisant calcul à 500 / s