View  Edit  Attributes  History  Attach  Print  Search

PYQTLAB

PyQt Lab' : Dessin :

Par X. HINAULT - Juin 2013

Ce que l'on va faire ici

  • Dans ce code PyQt, on va réaliser l'affichage de parasites TV dans un QPixmap et faire défiler 3 lignes RGB en avant plan.

Pré-requis

  • python 2.7
  • pyqt4.x

Téléchargement :

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: Tue Aug 20 20:46:28 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(341, 265)
        self.labelImage = QtGui.QLabel(Form)
        self.labelImage.setGeometry(QtCore.QRect(10, 15, 320, 240))
        self.labelImage.setStyleSheet(_fromUtf8("background-color: rgb(180, 180, 180);"))
        self.labelImage.setText(_fromUtf8(""))
        self.labelImage.setObjectName(_fromUtf8("labelImage"))

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

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Pyqt : dessin : parasites + lignes RGB", None, QtGui.QApplication.UnicodeUTF8))


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 time # temps - pour micros

import numpy as np # math et tableaux


from  tuto_pyqt_dessin_qpixmap_qimage_numpy_gray_timer_random 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

                # -- processing like
                self.width=self.labelImage.width() # hauteur
                self.height=self.labelImage.height() # largeur
                self.frameRate=40 # fps
                self.frameCount=0 # variable comptage nombre de frame

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

                # --- Code actif initial  ---

                #-- initialisation du Timer
                self.timerDraw=QTimer() # déclare un timer Qt
                self.timerDraw.start(1000/self.frameRate) # lance le timer - durée en ms
                self.connect(self.timerDraw, SIGNAL("timeout()"), self.timerDrawEvent) # 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...

                self.setup() # initialisation


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

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

        #-- fonction gestion survenue évènement Timer Draw
        def timerDrawEvent(self): # fonction appelée lors de la survenue d'un évènement Timer - nom de la fonction indiférrent
                print("Timer")
                self.frameCount=self.frameCount+1 # comptage des frames
                self.draw() # appelle fonction draw

        # --- fonctions de classes autres---    

        # fonction micros : renvoie le nombre de microsecondes courant de l'horloge système
        def micros(self):
                return(int(round(time.time() * 1000000))) # microsecondes de l'horloge système

        # fonction de MAJ du QPixmap : chargement QImage +/- dessin + affichage dans QLabel
        def updatePixmap(self):

                # chargement du QImage dans le QPixmap
                self.pixmap.convertFromImage(self.image) # recharge le QImage dans le QPixmap existant - met à jour le QPixmap

                # +/- dessin sur le Pixmap - ne modifie pas le QImage chargé
                self.painterPixmap=QPainter(self.pixmap) # associe QPainter (classe de dessin) au QPixmap

                # tracé ligne horizontale sur le Pixmap = laise QImage inchangé ++

                #valeur=239-valeurIn
                valeur=np.uint8(self.frameCount*4) # fait avancer ligne en fonction frameCount

                self.painterPixmap.setPen(QPen(QColor(255,0,0),2)) # fixe la couleur du crayon et la largeur pour le dessin - forme compactée          
                self.painterPixmap.drawLine(0,valeur,self.image.width(),valeur) # dessin rectangle : drawRect (self, int x, int y, int w, int h)

                self.painterPixmap.setPen(QPen(QColor(0,0,255),2)) # fixe la couleur du crayon et la largeur pour le dessin - forme compactée          
                if valeur<=128: self.painterPixmap.drawLine(0,valeur+127,self.image.width(),valeur+127) # dessin rectangle : drawRect (self, int x, int y, int w, int h)
                else: self.painterPixmap.drawLine(0,valeur-127,self.image.width(),valeur-127) # dessin rectangle : drawRect (self, int x, int y, int w, int h)

                self.painterPixmap.setPen(QPen(QColor(0,255,0),2)) # fixe la couleur du crayon et la largeur pour le dessin - forme compactée          
                self.painterPixmap.drawLine(0,self.height-valeur,self.image.width(),self.height-valeur) # dessin rectangle : drawRect (self, int x, int y, int w, int h)

                # il existe d'autres possibilités de dessin (polygone, chemin, etc..) voir : http://pyqt.sourceforge.net/Docs/PyQt4/qpainter.html

                self.painterPixmap.end() # ferme le painter - n'est plus accessible après

                #-- affichage du QPixmap dans QLabel
                self.labelImage.setPixmap(self.pixmap) # met à jour le qpixmap affiché dans le qlabel  

        #--- fonctions Processing like -------------

        # fonction setup appelée une seule fois au démarrage

        def setup(self):

                # dessin : créer image à partir tableau numpy

                # -- initialisation du tableau de pixels
                #self.pixels=np.zeros((self.labelImage.height(),self.labelImage.width()),np.uint8,'C') # tableau 320x240 x 1 canal et 8U
                self.pixels=127+(np.random.normal(size=(self.height,self.width)).astype(np.uint8)*64) # tableau 320x240 x 1 canal et 8U - attention inversion w,h

                # -- Initialisation du QImage 1 canal à partir du tableau Numpy
                #QImage(self,str data, int width, int height, Format format)
                self.image=QImage(self.pixels.tostring(), self.labelImage.width() , self.labelImage.height() ,QImage.Format_Indexed8) # crée image Gray 8 bits même taille que label

                #-- Initialisation du QPixmap d'affichage
                self.pixmap=QPixmap.fromImage(self.image) # initialise  le QPixmap...

                self.updatePixmap() # affichage initial du QPixmap

        # -------- fin setup -----------

        # fonction draw appelée à intervalle régulier fixée par framerate
        def draw(self):

                self.micros0=self.micros() # temps reference

                self.pixels=127+(np.random.normal(size=(self.height,self.width)).astype(np.uint8)*64) # tableau 320x240 x 1 canal et 8U
                self.image=QImage(self.pixels.tostring(), self.width , self.height ,QImage.Format_Indexed8) # crée image Gray 8 bits même taille que label
                self.updatePixmap() # affichage initial du QPixmap

                deltaMicros=self.micros()-self.micros0 # calcul délai          
                print str(deltaMicros)+" us" # affiche delai

        # -------- fin draw -----------


# -- 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 QPixmap affiche des parasites TV avec 3 lignes qui se défilent à l'avant plan.