0% ont trouvé ce document utile (0 vote)
61 vues71 pages

Graphismes avancés en PyQt

Ce document décrit les bases du dessin graphique en PyQt. Il présente les classes principales pour le dessin telles que QPainter, QPaintDevice et QPaintEngine. Il explique également comment gérer les événements souris dans un widget PyQt.

Transféré par

laurent capoeira
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
61 vues71 pages

Graphismes avancés en PyQt

Ce document décrit les bases du dessin graphique en PyQt. Il présente les classes principales pour le dessin telles que QPainter, QPaintDevice et QPaintEngine. Il explique également comment gérer les événements souris dans un widget PyQt.

Transféré par

laurent capoeira
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Graphismes en PyQt

Sylvain Malacria
[Link]
[Link]

Diapositives inspirées de Gilles Bailly


Objectifs

Introduction
‣ Signaux et slots
‣ Bases de PyQt
‣ Les principales classes Qt

Graphisme avancé
‣ Le dessin en PyQt
‣ Programmation événementielle
‣ Notion avancée de graphisme avec Qt
#1 Le dessin en PyQt
Dessin en PyQt
Paint system

QPainter QPaintEngine QPaintDevice

L’API de peinture de Qt permet de peindre à l’écran, dans un fichier, etc.


3 classes principales :
‣ QPainter pour effectuer des opérations de dessin
‣ QPaintDevice abstraction 2D dans laquelle on dessine
‣ QPaintEngine interface pour relier les deux
Dessin en PyQt
Paint system

QPainter QPaintDevice

L’API de peinture de Qt permet de peindre à l’écran, dans un fichier, etc.


3 classes principales :
‣ QPainter pour effectuer des opérations de dessin
‣ QPaintDevice abstraction 2D dans laquelle on dessine
‣ QPaintEngine interface pour relier les deux

QPaintEngine utilisée de manière interne (cachée) par QPainter et QPaintDevice


QPainter

QPainter est l’outil de dessin


‣ lignes simples
‣ path
‣ formes géometriques (ellipse, rectangle, etc.)
‣ texte
‣ images
‣ etc.
Utilise deux objets principaux
‣ QBrush (pour les fill)
‣ QPen (pour les stroke)
Fonction principale est de dessiner, mais dispose d’autres fonctions pour
optimiser son rendu
Peut dessiner sur n’importe quel objet qui hérite de la classe QPaintDevice
Exemples de QPaintDevice

Classe de base dans laquelle on peut peindre avec un QPainter


‣ QWidget
‣ QImage
‣ QPixmap
‣ QPicture
‣ QPrinter
‣ …
Dessiner dans un QWidget ?

Le widget se “dessine” lorsqu’il est repeint


Le widget est repeint lorsque :
‣ une fenêtre passe au dessus
‣ on redimensionne la fenêtre
‣ on lui demande explicitement
- Repaint(), force le widget à être redessiné
- Update(), un évènement de dessin est ajouté en file d’attente
Dessiner dans un QWidget ?

Le widget se “dessine” lorsqu’il est repeint


Le widget est repeint lorsque :
‣ une fenêtre passe au dessus
‣ on redimensionne la fenêtre
‣ on lui demande explicitement
- Repaint(), force le widget à être redessiné
- Update(), un évènement de dessin est ajouté en file d’attente

Dans tous les cas, c’est la méthode :


paintEvent(self, QPaintEvent)

qui est appelée (et vous ne devez jamais l’appeler manuellement)


0;0 x

y
0;0 x
1920;0

1080;0 1920;1080
Dessiner dans un QWidget

class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event): # event de type QPaintEvent
# Blabla de dessin ici

def main(args):
app = QApplication(args)
win = QMainWindow()
[Link](Dessin())
[Link](300,200)
[Link]()
app.exec_()
return

if __name__ == "__main__":
main([Link])
Dessiner dans un QWidget

class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event): # event de type QPaintEvent
painter = QPainter(self) # recupere le QPainter du widget
[Link](5,5,120,40) # dessiner un rectangle noir
return

def main(args):
app = QApplication(args)
win = QMainWindow()
[Link](Dessin())
[Link](300,200)
[Link]()
app.exec_()
return

if __name__ == "__main__":
main([Link])
Dessiner dans un QWidget
Pourquoi cela fonctionne?

class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event): # event de type QPaintEvent
painter = QPainter(self) # recupere le QPainter du widget
[Link](5,5,120,40) # dessiner un rectangle noir
return

QPainter QPaintDevice

QPainter comme outil de dessin


QWidget hérite de QPaintDevice
Dessin avancé

QPainter:
‣ DrawLine(), drawEllipse(), drawRect(), drawPath(), etc.
‣ fillRect(), fillEllipse()
‣ drawText()
‣ drawPixMap(), drawImage()
‣ setPen(), setBrush()

QPainter QPaintDevice
Dessin coloré

class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self) # recupere le QPainter du widget
[Link]([Link]) # add a red pen
[Link]([Link]) # set a light gray brush
[Link](5,5,120,40) # dessine le rectangle
Instancier un Pen

class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self) # recupere le QPainter du widget
pen = QPen([Link]) # instancier un pen
[Link](5) # change l'epaisseur
[Link](pen) # appliquer ce pen au painter
[Link]([Link]) # set a light gray brush
[Link](5,5,120,40) # dessine le rectangle
class Dessin(QWidget):

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
pen = QPen([Link])
[Link](5)
[Link](pen)
[Link]([Link])
[Link](5,5,120,40)
[Link](QColor(120, 255, 255, 150))
[Link](0,0,100,130)
Questions

Où dessiner?
‣ Dans la méthode paintEvent(self, QPaintEvent )
Comment demander le réaffichage d’un widget
‣ update()
‣ repaint()
Quelle est la différence entre update() et repaint()?
‣ update() indique qu’une zone est à réafficher (mais l’affichage n’est pas instantané)
‣ repaint() réaffiche immédiatement (mais peut introduire de la latence)
Comment dessiner dans paintEvent(QPaintEvent)
‣ instancier un QPainter: p = QPainter(self )

Dans quoi dessiner?

QPainter QPaintDevice

Tous ce qui hérite de QPaintDevice


‣ QWidget
‣ QPrinter
‣ QPixmap
‣ QImage
‣ etc.

Possibilité de rendu de “haut niveau” (SVG)


‣ QSvgRenderer
‣ QSvgwidget
#2 Gestion des évènements
Gestions des évènements souris dans un QWidget

Méthodes qui héritent de QWidget

def mouseMoveEvent(self, event):

def mousePressEvent(self, event):

def mouseReleaseEvent(self, event):

def enterEvent(self, event):

def leaveEvent(self, event):


class Dessin(QWidget):

def mousePressEvent(self, event): # evenement mousePress


[Link] = [Link]()
print("press: ", [Link])

def mouseReleaseEvent(self, event): # evenement mouseRelease


[Link] = [Link]()
print("release: ", [Link]())

193-51-236-93:TPs sylvain$ python3 [Link]


press: [Link](141, 28)
release: [Link](141, 28)
press: [Link](274, 129)
release: [Link](274, 129)

Les méthodes sont appelées automatiquement car la classe hérite de QWidget !!


class Dessin(QWidget):

def __init__(self):
super().__init__()
[Link](True) #activer le "mouse tracking"

def mouseMoveEvent(self, event): # evenement mouseMove


[Link] = [Link]()
print("move: ", [Link])

Par défaut, mouseMoveEvent envoyés seulement si bouton de souris enfoncé (Drag)

Possible d’activer/désactiver en permanence en utilisant setMouseTracking(bool)


Exemple

class Dessin(QWidget):

def __init__(self):
super().__init__()
[Link](True) # on active le mouseTracking
[Link] = None
def mouseMoveEvent(self, event): # evenement mouseMove
[Link] = [Link]() # on stocke la position du curseur
[Link]() # on met à jour l'affichage

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

if [Link] != None:
[Link](\
[Link].x()-5,\
[Link].y()-5,10,10) # On dessine l'ellipse autour du curseur
Exemple

class Dessin(QWidget):

def __init__(self):
super().__init__()
[Link](True) # on active le mouseTracking
[Link] = None
def mouseMoveEvent(self, event): # evenement mouseMove
[Link] = [Link]() # on stocke la position du curseur
[Link]() # on met à jour l'affichage

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

if [Link] != None:
[Link](\
[Link].x()-5,\
[Link].y()-5,10,10) # On dessine l'ellipse autour du curseur
Exemple

class Dessin(QWidget):

def __init__(self):
super().__init__()
[Link](True) # on active le mouseTracking
[Link] = None
def mouseMoveEvent(self, event): # evenement mouseMove
[Link] = [Link]() # on stocke la position du curseur
[Link]() # on met à jour l'affichage

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

if [Link] != None:
[Link](\
[Link].x()-5,\
[Link].y()-5,10,10) # On dessine l'ellipse autour du curseur
QMouseEvent

De type QMouseEvent

def mousePressEvent(self, event):

QMouseEvent permet de récupérer (selon versions) :


‣ button( ) : bouton souris qui a déclenché l’événement. ex: [Link]#Button
‣ buttons( ) : état des autres boutons. ex: [Link]#Button | [Link]
‣ modifiers( ) : modificateurs clavier. ex: [Link] | [Link]#Modifier
‣ pos( ) : position locale (relative au widget)
‣ globalPos( ), windowPos( ), screenPos( ) : position globale ou relative à ce référentiel
- utile si on déplace le widget interactivement !
Synthèse

événements def mousePressEvent(self, QMouseEvent):


......
......
update();
}
boucle de gestion
des événements
def mouseMoveEvent(self, QMouseEvent):
......
......
update();
}

def mouseReleaseEvent(QMouseEvent* e):


def paintEvent(self, QPaintEvent):
......
painter = QPainter(self ) ......
......
update();
return
}
#3 Dessin avancé
QPainter
Attributs

‣ setPen( ) : lignes et contours

‣ setBrush( ) : remplissage

‣ setFont( ) : texte

‣ setTransform( ), etc. : transformations affines

‣ setClipRect/Path/Region( ) : clipping (découpage)

‣ setCompositionMode( ) : composition
QPainter

Lignes et contours
‣ drawPoint(), drawPoints()
‣ drawLine(), drawLines()
‣ drawRect(), drawRects()
‣ drawArc(), drawEllipse()
‣ drawPolygon(), drawPolyline(), etc...
‣ drawPath() : chemin complexe

Remplissage
‣ fillRect(), fillPath()

Divers
‣ drawText()
‣ drawPixmap(), drawImage(), drawPicture()
‣ etc.
QPainter

Classes utiles
‣ entiers: QPoint, QLine, QRect, QPolygon

‣ flottants: QPointF, QLineF, ...

‣ chemin complexe: QPainterPath

‣ zone d’affichage: QRegion


Pinceau: QPen

Attributs
‣ style : type de ligne
‣ width : épaisseur
‣ brush : attributs du pinceau (couleur...)
‣ capStyle : terminaisons
‣ joinStyle : jointures

PenStyle

Cap Style

Join Style
Pinceau: QPen

Exemple
// dans méthode PaintEvent()

pen = QPen() // default pen


[Link]([Link])
[Link](3)
[Link]([Link])
[Link]([Link]) PenStyle
[Link]([Link])

Cap Style
painter = QPainter( self )
[Link]( pen )

Join Style
Remplissage: QBrush

Attributs
‣ style
BrushStyle
‣ color
‣ gradient
‣ texture

brush = QBrush( ... )

.....

painter = QPainter(self)

[Link](brush)
Remplissage: QBrush

Attributs
‣ style
‣ color
‣ gradient
‣ texture

QColor [Link]
‣ modèles RGB, HSV or CMYK
‣ composante alpha (transparence) :
- alpha blending

‣ couleurs prédéfinies:
- [Link]
Remplissage: gradients

Type de gradients
‣ lineaire,
‣ radial
‣ conique

gradient = QLinearGradient(QPointF(0, 0), QPointF(100, 100))


[Link](0,[Link])
[Link](1,[Link])
[Link](gradient)

QLinearGradient QRadialGradient QConicalGradient répétition: setSpread()


Composition

Modes de composition
‣ opérateurs de Porter Duff:
‣ définissent : F(source, destination)
‣ défaut : SourceOver
- avec alpha blending
- dst <= asrc * src + (1-asrc) * adst * dst

‣ limitations
- selon implémentation et Paint Device

Méthode:

setCompositionMode( )
Découpage (clipping)

Découpage
‣ selon un rectangle, une région ou un path
‣ méthodes de QPainter

setClipping(), setClipRect(), setClipRegion(), setClipPath()

QRegion
‣ united(), intersected(), subtracted(), xored()

r1 = QRegion( QRect(100, 100, 200, 80), [Link]) # r1: elliptic region


r2 = QRegion( QRect(100, 120, 90, 30) ) # r2: rectangular region
r3 = [Link](r2); # r3: intersection

painter = QPainter(self);
[Link](r3,[Link]);

...etc... // paint clipped graphics


Example

def paintEvent(self, event):


painter = QPainter(self)
[Link](QColor(255,0,0))
rect1 = QRect(10, 10, 100, 80)
rect2 = QRect(50, 2, 90, 130)
rect3 = QRect(5, 5, 100,100)

r1 = QRegion( rect1, [Link]) # definition des regions


r2 = QRegion( rect2)
rc = [Link](r2) # combinaison de regions

[Link](rc) # on attribue la clipregion


[Link](rect3) # on dessine

united() xor() intersected() subtracted()


Transformations affines

Transformations
‣ translate()
‣ rotate()
‣ scale()
‣ shear()
‣ setTransform()

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
[Link]() # empile l'état courant
[Link]([Link]()/2,
[Link]()/2) # on "centre" le painter

for k in range(0,10):
[Link](0, 0, 400, 0) # dessine une ligne
[Link](45) # rotation de 45°

[Link]() # dépile l'état courant


Anti-aliasing

Anti-aliasing
‣ éviter l’effet d’escalier
‣ particulièrement utile pour les polices de caractères

Subpixel rendering
‣ exemples : ClearType, texte sous MacOSX

MacOSX

ClearType
(Wikipedia)
Anti-aliasing

Anti-aliasing sous Qt

QPainter painter(this);

[Link]([Link]);

[Link]([Link]);

[Link](2, 7, 6, 1);

Rendering hints
‣ “hint” = option de rendu
- effet non garanti
- dépend de l’implémentation et du matériel

‣ méthode setRenderingHints( ) de QPainter


Anti-aliasing

[Link]([Link])

Avec Sans
Antialiasing et cordonnées

Epaisseurs impaire
‣ pixels dessinés à droite et en dessous
[Link]() = left() + width() -1
Dessin anti-aliasé [Link]() = top() + height() -1
Mieux : QRectF (en flottant)
‣ pixels répartis autour de la ligne idéale
Paths

QPainterPath
‣ figure composée d’une suite arbitraire de lignes et courbes
- affichée par: [Link]()
- peut aussi servir pour remplissage, profilage, découpage

Méthodes
‣ déplacements: moveTo(), arcMoveTo()
‣ dessin: lineTo(), arcTo()
‣ courbes de Bezier: quadTo(), cubicTo()
‣ addRect(), addEllipse(), addPolygon(), addPath() ...
‣ addText()
‣ translate(), union, addition, soustraction...
‣ et d’autres encore ...
Path
exemples

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
path = QPainterPath() #instancie le path
[Link](3, 3) # position initiale du path
[Link](50,130) # Tracé droit
[Link](120,30) # tracé droit
[Link](120,30,60,50,3,3) # tracé bezier
[Link](path) #dessiner le path
Path
exemples

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
path = QPainterPath() #instancie le path
[Link](3, 3) # position initiale du path
[Link](50,130) # Tracé droit
[Link](120,30) # tracé droit
[Link](120,30,60,50,3,3) # tracé bezier
[Link](path) #dessiner le path
Paths
exemples

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
center = QPointF([Link]()/2.0,[Link]()/2.0)
myPath = QPainterPath()
[Link]( center )
[Link]( QRectF(0,0,[Link](),[Link]()), 0, 270 )

[Link]([Link])
[Link]( myPath )

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
myPath = QPainterPath()
[Link](QPointF(40,60),QFont('SansSerif',50),"Qt")
[Link](myPath)
Paths

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

path = QPainterPath()
[Link](20, 20, 60, 60)
[Link](0, 0)
[Link](99, 0, 50, 50, 99, 99)
[Link](0, 99, 50, 50, 0, 0)

[Link](0, 0, 100, 100, [Link])


[Link]( QPen(QColor(79, 106, 25), 1,
[Link], [Link], [Link]))
[Link]( QColor(122, 163, 39));
[Link](path);

[Link] [Link]
(default)
Paths

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

path = QPainterPath()
[Link](20, 20, 60, 60)
[Link](0, 0)
[Link](99, 0, 50, 50, 99, 99)
[Link](0, 99, 50, 50, 0, 0)

[Link](0, 0, 100, 100, [Link])


[Link]( QPen(QColor(79, 106, 25), 1,
[Link], [Link], [Link]))
[Link]( QColor(122, 163, 39));
[Link](path);

[Link] [Link]
(default)
Paths

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)

path = QPainterPath()
[Link](20, 20, 60, 60)
[Link](0, 0)
[Link](99, 0, 50, 50, 99, 99)
[Link](0, 99, 50, 50, 0, 0)

[Link](0, 0, 100, 100, [Link])


[Link]( QPen(QColor(79, 106, 25), 1,
[Link], [Link], [Link]))
[Link]( QColor(122, 163, 39));
[Link](path);

[Link] [Link]
(default)
Surfaces d’affichage
Images

Types d’images
‣ QImage: optimisé pour E/S et accès/manipulation des pixels
- QPixmap, QBitmap : optimisés pour affichage l’écran

‣ QPicture: pour enregistrer et rejouer les commandes d’un QPainter

‣ dans tous les cas : on peut dessiner dedans avec un QPainter

Entrées/sorties
‣ load() / save() : depuis/vers un fichier, principaux formats supportés
‣ loadFromData() : depuis la mémoire
Accès aux pixels

Format 32 bits : accès direct


image = QImage(3, 3, QImage.Format_RGB32)

value = QRgb(122, 163, 39) // 0xff7aa327


[Link](0, 1, value)
[Link](1, 0, value)

Format 8 bits : indexé


image = QImage(3, 3, QImage::Format_Indexed8)

value = QRgb(122, 163, 39) // 0xff7aa327


[Link](0, value)

value = QRgb(237, 187, 51) // 0xffedba31


[Link](1, value)

[Link](0, 1, 0)
[Link](1, 0, 1)
Autres surfaces d’affichage

SVG
‣ QSvgWidget
- QSvgRenderer

OpenGL
‣ QGLWidget
- QGLPixelBuffer
- QGLFramebufferObject

Impression
‣ QPrinter

QSvgWidget
#4 Interaction avec formes géométriques
Picking

Picking avec QRect, QRectF


‣ intersects()
‣ contains()
Picking avec QPainterPath
‣ intersects(const QRectF & rectangle)
‣ intersects(const QPainterPath & path)
‣ contains(const QPointF & point)
‣ contains(const QRectF & rectangle)
‣ contains(const QPainterPath & path)
Retourne l’intersection
‣ QPainterPath intersected(const QPainterPath & path)
Picking / Interaction

Exemple
‣ teste si la souris est dans le rectangle quand on appuie sur le bouton de la souris
‣ change la couleur du rectangle à chaque clique

def __init__(self):
super().__init__()
[Link] = True # variable d'instance booleen
[Link] = QRect(5,5,140,120) # variable d'instance rectangle

def mousePressEvent(self, event): # evenement mousePress


[Link] = [Link]()
if [Link]([Link]()): # test la position
[Link] = not [Link]
[Link]() # demande la MAJ du dessin

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
if [Link]:
[Link]([Link])
else:
[Link](QColor([Link]))
[Link]([Link])
Formes non rectangulaires

Utilisation des regions


def __init__(self):
super().__init__()
[Link] = True # variable d'instance booleen
[Link] = QRect(5,5,140,120) # variable d'instance rectangle

def mousePressEvent(self, event): # evenement mousePress


[Link] = [Link]()
ellipse = QRegion([Link],[Link]) # défini une region elliptique
if [Link]([Link]()): # test la position
[Link] = not [Link]
[Link]() # demande la MAJ du dessin

#evenement QPaintEvent
def paintEvent(self, event):
painter = QPainter(self)
if [Link]:
[Link]([Link])
else:
[Link](QColor([Link]))
[Link]([Link])
#5 Performances de l’affichage
Performance de l’affichage

Problèmes classiques :
‣ Flickering et tearing (scintillement et déchirement)
‣ Lag (latence)
Flickering

Flickering
‣ scintillement de l’affichage car l’oeil perçoit les images intermédiaires
‣ exemple : pour rafraichir cette page il faut :
- 1) tout « effacer » (repeindre le fond)
- 2) tout redessiner
- => scintillement si le fond du transparent est sombre alors que le fond de la fenêtre est
blanc
Double buffering

Double buffering
‣ solution au flickering :
- dessin dans le back buffer
- recopie dans le front buffer (le buffer vidéo

qui contrôle ce qui est affiché sur l’écran)

‣ par défaut avec Qt4

source: AnandTech
Tearing

Possible problème : Tearing

‣ l’image apparait en 2 (ou 3...) parties horizontales


‣ problème : recopie du back buffer 

avant que le dessin soit complet
- mélange de plusieurs "frames" vidéo
- en particulier avec jeux vidéo et autres

applications graphiquement demandantes

source: AnandTech
Tearing

Solution au Tearing
‣ VSync (Vertical synchronization )
‣ rendu synchronisé avec l'affichage
‣ inconvénient : ralentit l'affichage

source: AnandTech
Performance de l’affichage

Latence (lag)
‣ effet : l’affichage «ne suit pas » l’interaction
‣ raison : le rendu n'est pas assez rapide
Performance de l’affichage

Latence (lag)
‣ effet : l’affichage ne suit pas l’interaction
‣ raison : le rendu n'est pas assez rapide
Solutions
‣ afficher moins de choses :
- dans l’espace

- dans le temps
‣ afficher en mode XOR
Performance de l’affichage

Afficher moins de choses dans l'espace


‣ Clipping : réduire la zone d'affichage
- méthodes rect() et region() de QPaintEvent

‣ "Backing store" ou équivalent


- 1) copier ce qui ne change pas dans une image
- 2) afficher cette image dans la zone de dessin
- 3) afficher la partie qui change par dessus
Performance de l’affichage

Afficher moins de choses dans le temps


‣ sauter les images intermédiaires :
- réafficher une fois sur deux… ou selon l'heure

‣ les timers peuvent être utiles (cf. QTimer)

void mouseMoveEvent(QMouseEvent* e)
......
événements
if (delay < MAX_DELAY) update();
}

boucle de gestion
des événements

Ne pas réafficher si le délai est trop long


Suivant le cas (et le toolkit), test dans une

de ces 2 fonctions
void paintEvent(QPaintEvent* e) {
if (delay > MAX_DELAY) return;
......
}

Vous aimerez peut-être aussi