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

  1. #1
    Membre régulier
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Points : 93
    Points
    93
    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 éprouvé

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

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Janvier 2006
    Messages : 621
    Points : 1 264
    Points
    1 264
    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 sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 691
    Points : 25 548
    Points
    25 548
    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é !

  4. #4
    Membre régulier
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Points : 93
    Points
    93
    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 régulier
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Points : 93
    Points
    93
    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 sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 691
    Points : 25 548
    Points
    25 548
    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

  7. #7
    Membre régulier
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Points : 93
    Points
    93
    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 sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 691
    Points : 25 548
    Points
    25 548
    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 ?

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

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

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 691
    Points : 25 548
    Points
    25 548
    Par défaut
    ClientRect n'existe que pour TCommonCustomForm contrairement à la VCL où ClientRect apparait dès TControl

    Là il c'est des FMX.TPanel donc pas de ClientRect !
    De plus le Paramètre ARect vient du OnPaint donc fourni par FMX, on espérer qu'il soit correct à l'arrondi près !

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 825
    Points : 13 565
    Points
    13 565
    Par défaut
    J'admets que mes connaissances en FMX sont nulles, mais c'est pas logique !
    Par contre, Form1.InvalidateRect(Panel1.BoundsRect) oui !

    Mais je ne vais pas vous saouler avec mon incompétence plus longtemps

    (Même si l'aide dit qu'il y a une transposition. Un ClientToParent en VCL...)

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 691
    Points : 25 548
    Points
    25 548
    Par défaut
    Mais tu nous saoule pas, surtout que j'ai la même incompétence que toi au niveau FMX puisque je n'ai que compiler les Démo et rien de plus

    Et notes qu'avait proposé comme toi d'essayer toutes les variantes ARect, ClipRect ou LocalRect ...


    C'est justement très intéressant de devoir se remettre en cause et de voir qu'il faut penser différemment en FMX qu'en VCL

    Ma seule compétence est de savoir chercher dans l'aide et de fournir les liens et d'extrapoler par rapport à un survol des fichiers PAS de FMX
    J'ai eu ÉNORMÉMENT de chance jusqu'à présent avec mes théories (qui ont été mises en pratique )

    Comme en FMX tout est du dessin, il n'y a pas de contrôle GDI comme en mode VCL, il n'y a pas de Handle et une vrai imbrication logique comme sous Windows !
    Sinon faudrait que FMX gère les controles de chaque OS et leur limitation, on a vu ce que donnait CLX\QT

    Donc, lorsque tu dessines, un Panel, en fait, cela doit en fait dessiner sur le "Top Parent" (la Form) donc effectuer des translations effectivement !
    Si en séparant d'un Pixel, les deux panels, cela évite le problème, ça sent des erreurs d'arrondis !
    Faudrait tester, en mettant différente taille au panel Top !

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 825
    Points : 13 565
    Points
    13 565
    Par défaut
    Alors encore une p'tite pour la route

    Sur le principe, je comprend très bien. J'avais d'ailleurs fait un FMX en GDI il n'y a pas si longtemps

  14. #14
    Membre régulier
    Inscrit en
    Août 2010
    Messages
    123
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 123
    Points : 93
    Points
    93
    Par défaut
    Effectivement, si on réduit BoundsRect de 2 pixels (et pas moins), ça permet d'éviter le problème. Pourquoi 2 pixels ? je n'en ai aucune idée. Par contre dans ce cas, les pixels au bord du Panel ne sont effectivement pas rafraîchis (gênant mais logique)...

    Après c'est peut être cet appel manuel InvalidateRect qui pose problème. Je dois pouvoir tester ça... demain.

    @Andnotor : si tu connais la réponse, ne te fais pas prier

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, 13h34
  2. Problème return sur une méthode
    Par root76 dans le forum Langage
    Réponses: 3
    Dernier message: 07/03/2008, 11h43
  3. Problème sur lancement distant de méthode
    Par alexandreSeven dans le forum Langage
    Réponses: 3
    Dernier message: 03/03/2008, 09h30
  4. Réponses: 7
    Dernier message: 12/02/2008, 19h12
  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, 21h16

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