IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Composant graphique : clignotement génant des bmp


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de marcootz
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 159
    Par défaut Composant graphique : clignotement génant des bmp
    Salut à tous,

    J'ai créé un composant graphique pour mon utilisation personnelle à l'aide de ce tuto : http://chgi.developpez.com/compo9/

    Ce composant représente un voyant avec trois positions et contient donc 3 images bmp, qui changent en fonction d'une propriété.

    Mon souci est que ce composant clignote très rapidement à une intervalle de temps aléatoire, càd pendant quelques millisecondes il disparait puis réapparait, même en mode édition de la form. C'est sûrement dû à un rafraichissement des bmp sur la form.
    Ce problème est assez génant quand il y a plusieurs de ce composant sur une form car ces clignotements attirent l'oeil, j'aimerais donc savoir si il n'y a pas une solution pour éviter ca.

    Voici un extrait du code du composant :
    le timer sert à éviter d'appeler la méthode "repaint" après avoir changer la propriété "position". Si je ne met pas ce timer le clignotement n'est plus visible

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    __fastcall TLed3Positions::TLed3Positions(TComponent* Owner)
    	: TGraphicControl(Owner)
    {
    		l_off = new Graphics::TBitmap();
    		l_off->LoadFromResourceName((int)HInstance, "LED3ETATOFF");
            l_on = new Graphics::TBitmap();
    		l_on->LoadFromResourceName((int)HInstance, "LED3ETATVERT");
    		l_alarme = new Graphics::TBitmap();
    		l_alarme->LoadFromResourceName((int)HInstance, "LED3ETATROUGE");
            Width = l_off->Width;
            Height = l_off->Height;
            l_off->Transparent = false;
    		l_on->Transparent = false;
    		l_alarme->Transparent = false;
            allume = 0;
     
            Timer1 = new TTimer(NULL);
            Timer1->Interval = 200;
    		Timer1->OnTimer = Tempo;
    }
    //---------------------------------------------------------------------------
    __fastcall TLed3Positions::~TLed3Positions()
    {
            delete l_off;
    		delete l_on;
    		delete l_alarme;
            delete Timer1;
    }
    //---------------------------------------------------------------------------
    void __fastcall TLed3Positions::Paint()
    {
            allume = Fmode;
    		if(allume==0) Canvas->Draw(0, 0,l_off);
    		else if(allume==1)   Canvas->Draw(0, 0,l_on);
    		else  Canvas->Draw(0, 0,l_alarme);
    		Canvas->Refresh();
    }
    //---------------------------------------------------------------------------
    // Rafraichissement du dessin selon le tempo.
    void __fastcall TLed3Positions::Tempo(TObject* Sender)
    {
           Invalidate();
    }
     
    //---------------------------------------------------------------------------
    namespace Led3positions
    {
    	void __fastcall PACKAGE Register()
    	{
    		TComponentClass classes[1] = {__classid(TLed3Positions)};
    		RegisterComponents("Leds", classes, 0);
    	}
    }
    //---------------------------------------------------------------------------
    Une idée ? Merci
    Marcootz

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 408
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 408
    Par défaut
    Salut !

    A titre perso, j'aurais été un peu plus loin dans le développement en utilisant un tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private :
    int On; //flip-flop
    Graphics::TBitmap *Cycle[2];
    Dans le Setter de la propriété qui fixe l'état (froid, normal, chaud) j'aurais fait comme ça :
    (Blue, Green ... sont les bitmaps):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    void __fastcall jLed::SetStatus(int Value)
    {
    if(FStatus != Value)
        {
        FStatus = Value;
        switch(Value)
            {
            case 0 :
            //Blue ne clignote pas
                Cycle[0] = Blue;
                Cycle[1] = Blue;
            break;
            case 1 :
            //Green clignote lentement
                Cycle[0] = Green;
                Cycle[1] = Lime;
                Timer->Interval = 400;
                break;
            case 2 :
            //Red clignote rapidement
                Cycle[0] = Maroon;
                Cycle[1] = Red;
                Timer->Interval = 200;
                break;
            }
        Repaint();
        }
    }
    La Paint devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void __fastcall jLed::Paint()
    {
    if((Cycle[0] != NULL) && (Cycle[1] != NULL))
        {
        Canvas->Draw(0,0, Cycle[On]);
        }
    }
    La OnTimer devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void __fastcall jLed::TimeOut(TObject *Sender)
    {
    On = On ^ 1; //Flip-flop basique
    Repaint();
    }
    A ce stade, chez moi ça ne scintille pas (et pourtant mon ordi... ) !

    A plus !

  3. #3
    Membre confirmé Avatar de marcootz
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 159
    Par défaut
    Salut henderson,
    Merci pour ta réponse, je vais essayer ta méthode. J'ai juste une petite question : Comment est appelé la méthode "SetStatus" ? Est ce une fonction système ou alors il faut l'appeler dans la timer ??

  4. #4
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Par défaut
    J'ai souvent eu ce genre de problème avec les composants dérivés de TGraphicControl.

    C'est pour cela qu'il faut utiliser un composant dérivé de TCustomControl pour éviter les scintillements :
    - DoubleBuffered = true permet d'éviter les scintillements (DoubleBuffered : Détermine si l'image du contrôle est restituée directement dans la fenêtre ou si elle est d'abord dessinée dans un bitmap en mémoire.)
    - Utiliser aussi la méthode Invalidate() plutôt que Repaint().

    Exemple d'un composant PaintBox qui ne scintille jamais.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class PACKAGE TBufferedPaintBox : public TCustomControl
    {
    private:
        TNotifyEvent FOnPaint;
    protected:
        virtual void __fastcall Paint(void);
    public:
        __fastcall TBufferedPaintBox(TComponent* Owner);
    __published:
        __property Align;
        __property Canvas;
        __property OnClick;
        __property OnMouseDown;
        __property OnMouseMove;
        __property OnMouseUp;
        __property OnResize;
        __property TNotifyEvent OnPaint =  {read=FOnPaint, write=FOnPaint};
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "BufferedPaintBox.h"
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
    //  ValidCtrCheck est utilisé pour vérifier que les composants créés n'ont
    // aucune fonction virtuelle pure.
    //
     
    static inline void ValidCtrCheck(TBufferedPaintBox *)
    {
        new TBufferedPaintBox(NULL);
    }
    //---------------------------------------------------------------------------
    __fastcall TBufferedPaintBox::TBufferedPaintBox(TComponent* Owner)
        : TCustomControl(Owner)
    {
        DoubleBuffered = true;
        ControlStyle = ControlStyle << csAcceptsControls;
    }
    //---------------------------------------------------------------------------
    namespace Bufferedpaintbox
    {
        void __fastcall PACKAGE Register()
        {
             TComponentClass classes[1] = {__classid(TBufferedPaintBox)};
             RegisterComponents("MyComponents", classes, 0);
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TBufferedPaintBox::Paint(void)
    {
        if (FOnPaint) FOnPaint(this);
    }

  5. #5
    Membre confirmé Avatar de marcootz
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 159
    Par défaut
    C'est bon à savoir !
    Merci slylafone

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 408
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 408
    Par défaut
    Salut !

    SetStatus est le Setter de la propriété Status, (méthode liée à l'écriture).

    Si l'utilisateur écrit :

    Après compilation, c'est exécuté comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Led->SetStatus(1);
    Donc dans la classe, on organise de cette manière là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    private :
     
    int FStatus;
     
    protected :
     
        void __fastcall SetStatus(int Value);
     
    public : 
     
        //...
     
    __published :
     
        __property int Status={read=FStatus, write=SetStatus};
    Comme chez moi cette classe est volante (je n'en ai pas fait un composant pour la palette), cette propriété est seulement public.
    De ton coté, elle devrait être published pour la faire apparaître dans l'inspecteur d'objet.

    Il faudrait tester dans cette méthode (SetStatus) si Value correspond bien à celles qui sont attendues :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if((Value >= 0) && (Value < 3) && (Value != FStatus)) 
    ...
    On peut aussi utiliser une énumération (enum) mais dans ce cas, il faudrait changer le type de la propriété...

    A plus !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Les composants graphiques sont-ils des controles ActiveX
    Par Lucas Panny dans le forum C++Builder
    Réponses: 0
    Dernier message: 02/11/2007, 05h55
  2. Sérialisation des composants graphiques
    Par sironimo dans le forum Interfaces Graphiques en Java
    Réponses: 6
    Dernier message: 23/01/2007, 11h35
  3. effectuer des operations sur les composants graphiques
    Par Zorgz dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 19/10/2006, 14h34
  4. Réponses: 4
    Dernier message: 15/12/2005, 22h36
  5. Activer et désactiver des composant graphiques?
    Par redabadache3 dans le forum Débuter
    Réponses: 1
    Dernier message: 16/08/2005, 17h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo