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

Composants FMX Delphi Discussion :

Problème sur la méthode InvalidateRect


Sujet :

Composants FMX Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut Problème sur la méthode InvalidateRect
    Bonjour,

    Voilà j'ai un problème avec la méthode InvalidateRect (je dessine sur le Canvas d'un TPanel). Pour redessiner mon graphique, j'utilise cette méthode :
    Panel1->InvalidateRect(Panel1->BoundsRect);
    Panel1 est bien redessiné, mais cette méthode semble "perturber" mon Panel2 (qui touche Panel1) : Panel2 appelle également sa méthode OnPaint... par contre le Canvas reste bloqué, Panel2 ne se met pas à jour...

    Je ne sais pas si quelqu'un a déjà eu ce type de problème, où si quelque chose m'échappe dans Firemonkey...
    Bref, toute aide sera appreciée.

  2. #2
    Membre éclairé

    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Janvier 2006
    Messages
    621
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Janvier 2006
    Messages : 621
    Par défaut
    Bonjour,
    je sais pas si ça va aider, masi ton panel2, il touche ou il recouvre même très partiellement ton panel1 ? Tu as essayé de les séparer d'au moins un pixel ?
    Autre piste possible, tu n'aurais pas un controle mal défini ou à cheval sur les deux ?

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Le Panel est-il Transparent en FMX comme il l'est en VCL avec ParentBackGround ?

    Si oui, si tu dessin Panel1 et qu'il y a un recouvrement (même d'un Pixel), il doit surement dessiner Panel2 pour avoir le Fond sous Panel1 puis dessiner ce dernier

    Par contre, si il se touche sans recouvrement, étrange, peut-être que ton Rectangle en paramètre d'InvalidateRect est trop grand, qu'il affecte le Control en dessous et ceux à côté !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Bonjour et merci pour vos réponses.

    En fait, j'ai Panel1 aligné en alClient, et Panel2 aligné en alTop. Donc ils se touchent mais à priori ne se recouvrent pas.

    Pour tester, je ne dessine plus rien dans Panel1, mais Panel1->InvalidateRect(...) déclenche toujours l’événement Panel2->OnPaint() !

    Par contre, effectivement, si je mets une séparation d'au moins 2 pixels entre les 2 panels (padding), ils ne se "perturbent" plus... Franchement, je ne comprend pas, car j'ai testé sur une autre fenêtre, et je ne retrouve pas ce problème...

    J'ai également un autre problème d'affichage (qui pourrait être lié) : Lorsque je dessine sur Panel1, parfois (lorsque j’interagis avec l'interface) l'affichage déborde sur certains composants environnants (Layout et Splitter en général). Dans Panel1, je dessine des lignes et les lignes ne sont pas forcement dans le rectangle client car j'applique un zoom et des rotations...

    Bref, plusieurs petits problèmes désagréables.

  5. #5
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Finalement j'arrive à reproduire mon problème :
    - Nouvelle fiche
    - Panel1 aligné alTop
    - Panel2 aligné alClient
    - Timer1

    Et voici le code de la fiche :
    Code c++ : 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
     //---------------------------------------------------------------------------
    #include <fmx.h>
    #pragma hdrstop
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.fmx"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    :TForm(Owner)
    {
    	Timer1->Interval = 25;
    }
     
    void __fastcall TForm1::Panel1Paint(TObject *Sender, TCanvas *Canvas, const TRectF &ARect)
    {
    	static int repaint = 0; repaint++;
    	Canvas->Fill->Color = 0xFF000000;
    	Canvas->Stroke->Color = 0xFF000000;
    	Canvas->FillText(ARect, repaint, false, 1.0, TFillTextFlags(), TTextAlign::taCenter, TTextAlign::taCenter);
    	Canvas->DrawLine(ARect.TopLeft(), TPointF(500.0, 1000.0), 1.0);
    }
     
    void __fastcall TForm1::Panel2Paint(TObject *Sender, TCanvas *Canvas, const TRectF &ARect)
    {
    	static int repaint = 0; repaint++;
    	Canvas->Fill->Color = 0xFF000000;
    	Canvas->Stroke->Color = 0xFF000000;
    	Canvas->FillText(ARect, repaint, false, 1.0, TFillTextFlags(), TTextAlign::taCenter, TTextAlign::taCenter);
    	Canvas->DrawLine(ARect.TopLeft(), ARect.BottomRight(), 1.0);
    }
     
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    	Panel1->InvalidateRect(Panel1->BoundsRect);
    }

    Lorsque l'on redimensionne la fiche, on voit que la méthode Panel2Paint a été appelée autant de fois que Panel1Paint (et pourtant l'affichage ne s'est pas mis à jour).

    Par contre, si on met un Splitter entre les deux panels, il n'y a plus ce problème. Mais là mon autre problème apparait, le Splitter peut être "perturbé" par l'affichage de Panel1.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Que vient faire le redimensionnement ?
    Forcer un panel en Bottom va suivre la taille de la fenêtre donc être redessiné !

    Cela se produit uniquement en présence du Timer ?
    Est-ce que Timer nuit à l'affichage de Panel2 ou alors il corrige celui de Panel1 ?
    TPointF(500.0, 1000.0) cela ne déborde-t-il pas sur le Canvas de la TForm ou même du Panel2 ?



    On a eu sujet similaire sur un mauvais refresh en FMX
    Faudrait voir si il ne serait pas plus propre de créer une Animation que d'utiliser un Timer ?

    Cela me rappel en D4, un Panel Top + un Splitter Top avec une Color différente de clBtnFace pouvait "baver" sur la zone MDI

    Canvas pointe bien sur le paramètre, pas de conflit avec un this->Canvas ?


    PS : utilise [code=c++] pour mettre du c++ dans la section delphi qui par défaut utilise la coloration du pascal
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre confirmé
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Par défaut
    Désolé ShaiLeTroll, je ne suis peut être pas très clair.

    Que vient faire le redimensionnement ?
    Le redimensionnement met à jour l'affichage des composants. Donc Panel1->OnPaint et Panel2->OnPaint sont appelés.
    On voit alors que la variable repaint dans Panel2->OnPaint a la même valeur que celle de Panel1->OnPaint !!!

    Forcer un panel en Bottom va suivre la taille de la fenêtre donc être redessiné !
    Je me suis trompé : alignement de Panel2 en alClient au lieu de alBottom. Le redessiner est le but recherché.

    Cela se produit uniquement en présence du Timer ?
    Est-ce que Timer nuit à l'affichage de Panel2 ou alors il corrige celui de Panel1 ?
    Non on peut mettre un bouton au lieu de Timer : mêmes conséquences. Je ne pense pas que le Timer pose problème.

    TPointF(500.0, 1000.0) cela ne déborde-t-il pas sur le Canvas de la TForm ou même du Panel2 ?
    On peut le changer en ARect.BottomRight() : mêmes conséquences.

    Canvas pointe bien sur le paramètre, pas de conflit avec un this->Canvas ?
    J'ai vérifié : pas de problème de ce coté là.

    Bref, je pense qu'il s'agit d'un bug de Firemonkey. La seule solution que je trouve pour l'instant : mettre un espace (un rectangle) entre les panels pour ne pas qu'ils se perturbent. Une autre solution est de réduire le TRect de 2 pixels dans la méthode InvalidateRect, mais l'affichage est alors coupé.

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    As-tu une différence avec ClipRect ou LocalRect,
    Compare les valeurs avec le paramètre ARect

    Souvent dans la VCL, tu as ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Panel1->InvalidateRect(InflateRect(Panel1->BoundsRect, -1, -1));
    En FMX, les coordonnées sont en Single, me dit pas qu'il y a un effort de bord lié à l'arrondi !


    Sinon, ce bug ne se produit qu'avec un appel manuel de InvalidateRect ?
    Si tu laisse tes deux Panels se redimensionner tu n'as pas de problème ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 934
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 934
    Par défaut
    InvalidateRect devrait logiquement être relatif à la zone cliente du contrôle. Donc, utiliser ClientRect plutôt que BoundsRect.

Discussions similaires

  1. vlookup avec problème sur la méthode range
    Par Nako_lito dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 15/09/2009, 12h34
  2. Problème return sur une méthode
    Par root76 dans le forum Langage
    Réponses: 3
    Dernier message: 07/03/2008, 10h43
  3. Problème sur lancement distant de méthode
    Par alexandreSeven dans le forum Langage
    Réponses: 3
    Dernier message: 03/03/2008, 08h30
  4. Réponses: 7
    Dernier message: 12/02/2008, 18h12
  5. Problème d'exposant sur une méthode mathématique.
    Par ecobarito dans le forum Débuter
    Réponses: 14
    Dernier message: 29/08/2007, 20h16

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