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 :

De l'utilisation de ArcDial


Sujet :

Composants FMX Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 633
    Billets dans le blog
    65
    Par défaut De l'utilisation de ArcDial
    Bonjour,

    Toujours dans mes délires de composants FMX (maintenant que j'ai trouvé comment faire des liens) je suis parti sur la création d'un compas "numérique"
    Nom : Capture.PNG
Affichages : 393
Taille : 3,7 Ko

    Cependant je n'arrive pas à maitriser ArcDial. Sur l'image, le bouton pointe au Nord (en fait le 0, obtenu au Nord grâce à une rotation de -90)
    Nom : Capture_1.PNG
Affichages : 377
Taille : 17,1 Ko
    cependant quand je tourne le bouton vers la droite (vers l'Est donc en théorie) je me retouve avec des valeurs négatives et donc vers l'Ouest !

    je m'en suis sorti en multipliant ArcDial.Value par -1 mais est-ce la seule solution ?

    // dans ce code test, c'est avant la liaison par livebindings
    // en fait c'est pour l'instant sans unité spéciale pour écrire le composant,
    // l'objet étant de tester l'affichage (graduations)

    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
    56
    57
    58
    59
    60
    procedure TForm1.ArcDial1Change(Sender: TObject);
    var i,ng,s : integer;
        Angle : single;
    begin
    GridLayout1.BeginUpdate;
    GridLayout1.DeleteChildren;
     
    Angle:=Trunc(ArcDial1.Value)*-1;
    ng:=Trunc(GridLayout1.Width/10);
    s:=Trunc(Angle)-(ng div 2);
    for i:= s to Trunc(Angle)+(ng div 2)
       do DrawGraduation(GridLayout1,round(degnormalize(i)));
    GridLayout1.EndUpdate;
    end;
     
    procedure TForm1.drawgraduation(const P : TGridLayout; d : integer);
    var PRectangle : TRectangle;
    begin
         PRectangle:= TRectangle.Create(P);
         with PRectangle do
           begin
             Width:=4;
             with TText.Create(PRectangle) do
             begin
               Height:=20;
               Width:=30;
               Align:=TAlignLayout.Center;
               Parent:=PRectangle;
               Margins.Top:=50;
               Font.Style:=[TFontStyle.fsBold];
               case d of
                    0  : Text:=North;
                    45 : Text:=NorthEast;
                    90 : Text:=East;
                    135: Text:=SouthEast;
                    180: Text:=South;
                    225: Text:=SouthWest;
                    270: Text:=West;
                    315: Text:=NorthWest;
                    else begin
                      if (d mod 10)=0 then begin
                            Text:=Format('%d°',[d]);
                        Margins.Top:=30;
                        Font.Style:=[TFontStyle.fsItalic];
                      end;
                    end;
               end;
             end;
             Margins.Bottom:=8;
             if (d mod 10)=0 then Margins.Bottom:=0
             else if (d mod 5)=0 then Margins.Bottom:=5;
     
             margins.left:=3;
             margins.Right:=4;
             Stroke.Kind:=TBrushKind.None;
             Fill.Color:=TAlphaColors.Black;
             Align:=TAlignLayout.Top;
            end;
         P.AddObject(pRectangle);
    end;

  2. #2
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    hello, je ne sais pas pour ta question, mais ton code me pique les yeux

    pourquoi détruire et reconstruire tous les éléments à chaque fois ? à vu de nez tu as toujours le même nombre de composants, il suffit donc d'ajuster leurs propriétés non ?
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 633
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    pourquoi détruire et reconstruire tous les éléments à chaque fois ? à vue de nez tu as toujours le même nombre de composants, il suffit donc d'ajuster leurs propriétés non ?
    Comme je l'ai écrit un premier essai, il a l'avantage d'avoir une sensation de défilement horizontal.
    Ton nez n'est pas tout à fait assez long, le nombre de composants dépend de la largeur du compas donc en cas de resize c'est à refaire, ne pas oublier que mon objectif est un futur composant (donc une procedure Paint quelque part)

    Mais je n'ai pas encore testé en changeant simplement les propriétés lors d'un changement de valeur, pas sûr que l'effet soit identique, wait and see !

  4. #4
    Membre confirmé

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 82
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    je m'en suis sorti en multipliant ArcDial.Value par -1 mais est-ce la seule solution ?
    J'ai regardé le code de TArcDial dans l'unité FMX.StdCtrls. Ce sont bien les conventions mathématiques standards qui sont utilisées:
    1) les angles sont comptés dans le sens direct, c'est-à-dire dans le sens inverse de celui des aiguilles d'une montre.
    2) l'origine des angles (quand on a juste posé le composant sur la fiche) est sur l'axe horizontal dans le sens positif.

    Donc, dans l'exemple de SergioMaster, le point "Est" correspond à 0° (Arcdial.Value) et l'angle de "Est" à "Nord" vaut +90°.
    Mais ce qui est trompeur et peut faire penser que les angles seraient comptés dans le sens des aiguilles d'une montre, c'est que l'orientation du bouton (Arcdial.RotationAngle) est mesurée par l'angle de la rotation d'ensemble du bouton (matérialisée par le point qu'on entraîne avec la souris). Mais ici intervient un résultat mathématique (contre intuitif mais facile à montrer) : la transformation des coordonnées d'un point dans un repère tournant est la rotation inverse (c'est-à-dire d'angle opposé) de la rotation qui change ce point dans le repère initial. D'où la valeur Arcdial.RotationAngle = - 90° pour faire passer l'origine du bouton de "Est" à "Nord".

    (Accessoirement, le code qui donne la valeur de l'angle entre deux points (fonction AngleBetween) me semble inutilement compliqué: il utilise seulement la fonction ArcCos de System.Math en oubliant la fonction AcrTan2 plus adaptée et présente dans la même unité)

  5. #5
    Membre Expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Mais je n'ai pas encore testé en changeant simplement les propriétés lors d'un changement de valeur, pas sûr que l'effet soit identique, wait and see !
    tu es en FMX, amuse toi aussi avec les TFloatAnimation (bon, ok, ça peut foutre le bordel quand on en fout partout, mais sont sympa des fois)

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 633
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    @Patrick pas besoin de floatanimation(s), pour le démontrer voilà une petite vidéo de mes ébauches ("Thermomètre", "Spinner" et "Compas")
    https://serge-girard.developpez.com/...tsebauche.webm

    Et, pour re-répondre @Paul, effectivement si mon nombre de graduation restait toujours identique (une propriété de mon composant) il serait envisageable de jouer sur la propriété des rectangles enfants. Je vais faire un essai.

    OK, ce n'est pas encore, loin d'être, une panacée : des composants aboutis.
    Seul mon "Thermometre" est dans une unité séparée et dans un dpk. Il y a beaucoup d'amélioration à y apporter :
    - des graduations
    - un réservoir en bas
    - un maximum/minimum de température et bien entendu la prise en compte de ceux-ci

    Mais Gouyon s'en est déjà chargé . La discussion qui s'en est suivi vous expliquera la suite

    Voici mon composant test
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    unit CThermometre;
     
    interface
     
    uses
      System.SysUtils, System.Classes, System.UITypes,
      FMX.Types, FMX.Controls, FMX.Objects,FMX.Graphics,
      Data.Bind.Components;
     
    type
      [ObservableMembers('Progress',false)]
      TThermometre = class(TRectangle)
      private
        FProgress: integer;
        procedure SetProgress(const Value: integer);
        procedure ObserverToggle(const AObserver: IObserver; const Value: Boolean);
        { Déclarations privées }
      protected
        { Déclarations protégées }
        function CanObserve(const ID: Integer): Boolean; override;  { declaration is in System.Classes }
        procedure ObserverAdded(const ID: Integer; const Observer: IObserver); override; { declaration is in System.Classes }
        procedure OnResize;
      public
        constructor Create(AOwner: TComponent); override;
        function Paint: Boolean; reintroduce;
        { Déclarations publiques }
      published
        { Déclarations publiées }
        property Progress : integer {read FProgress} write SetProgress;
      end;
     
    procedure Register;
     
    implementation
     
    procedure Register;
    begin
      RegisterComponents('Samples', [TThermometre]);
    end;
     
    { TRectangle1 }
     
    function TThermometre.CanObserve(const ID: Integer): Boolean;
    begin
     case ID of
        TObserverMapping.EditLinkID, TObserverMapping.ControlValueID:
          Result := True;
      else
        Result := False;
      end;
    end;
     
    constructor TThermometre.create(AOwner: TComponent);
    var pos : single;
        aBrush : TBrush;
    begin
      if not(csloading in ComponentState) then
      begin
        inherited;
        width:=30;
        height:=110;
        Xradius:=10;
        Yradius:=10;
        FProgress:=50;
        pos:=0.5;
        if pos=1 then pos:=1-0.000001;
        aBrush:=TBrush.Create(TBrushKind.Gradient,Talphacolors.null);
        try
          aBrush.Gradient.StartPosition.X:=0.5;
          aBrush.Gradient.StartPosition.Y:=1;
          aBrush.Gradient.StopPosition.X:=0.5;
          aBrush.Gradient.StopPosition.Y:=0;
          aBrush.Gradient.Points.Clear;
          aBrush.Gradient.Points.Add;
          aBrush.Gradient.Points[0].Color:=Talphacolors.red;
          aBrush.Gradient.Points[0].Offset:=0;
          aBrush.Gradient.Points.Add;
          aBrush.Gradient.Points[1].Color:=Talphacolors.red;
          aBrush.Gradient.Points[1].Offset:=pos;
          aBrush.Gradient.Points.Add;
          aBrush.Gradient.Points[2].Color:=Talphacolors.null;
          aBrush.Gradient.Points[2].Offset:=pos+0.000001;
          aBrush.Gradient.Points.Add;
          aBrush.Gradient.Points[3].Color:=Talphacolors.null;
          aBrush.Gradient.Points[3].Offset:=1;
          Fill:=aBrush;
        finally
         aBrush.Free;
        end;
      end;
    end;
     
    procedure TThermometre.ObserverAdded(const ID: Integer;
      const Observer: IObserver);
    begin
      if ID = TObserverMapping.EditLinkID then
        Observer.OnObserverToggle := ObserverToggle;
    end;
     
    procedure TThermometre.ObserverToggle(const AObserver: IObserver;
      const Value: Boolean);
    var
      LEditLinkObserver: IEditLinkObserver;
    begin
      if Value then
      begin
        if Supports(AObserver, IEditLinkObserver, LEditLinkObserver) then
          Enabled := not LEditLinkObserver.IsReadOnly;
      end
      else
        Enabled := True;
    end;
     
    procedure TThermometre.OnResize;
    begin
    Paint;
    end;
     
    function TThermometre.Paint: Boolean;
    var pos : single;
    begin
    BeginUpDate;
    pos:=(FProgress/100);
    if pos=1 then pos:=1-0.000001;
     
    Fill.Gradient.Points.Clear;
    Fill.Gradient.Points.Add;
    Fill.Gradient.Points[0].Color:=Talphacolors.red;
    Fill.Gradient.Points[0].Offset:=0;
    Fill.Gradient.Points.Add;
    Fill.Gradient.Points[1].Color:=Talphacolors.red;
    Fill.Gradient.Points[1].Offset:=pos;
    Fill.Gradient.Points.Add;
    Fill.Gradient.Points[2].Color:=Talphacolors.null;
    Fill.Gradient.Points[2].Offset:=pos+0.000001;
    Fill.Gradient.Points.Add;
    Fill.Gradient.Points[3].Color:=Talphacolors.null;
    Fill.Gradient.Points[3].Offset:=1;
     
    EndUpdate;
    result:=true;
    end;
     
    procedure TThermometre.SetProgress(const Value: integer);
    begin
      if FProgress<>Value then
       begin
        FProgress := Value;
        Paint;
       end;
    end;
     
     
     
    initialization
     
    Data.Bind.Components.RegisterValuePropertyName
      (TArray<TClass>.create(TThermometre), 'Progress', 'FMX');
     
    finalization
     
    Data.Bind.Components.UnregisterValuePropertyName
      (TArray<TClass>.create(TThermometre));
    end.

    Mon seul objectif de départ était de trouver un moyen de faire des liens LinkPropertyToField plutôt que LinkControlToField entre composants et données
    (toute la différence entre Field1 vers Progress des "thermomètres" et Field1 ver SelectedValue) de fil en aiguille j'en ai concoté plusieurs.

    Nom : Capture.PNG
Affichages : 337
Taille : 21,7 Ko

    La documentation de base ne proposait que le LinkControlToField (bidirectionnel) en utilisant Data.Bind.Components.RegisterObservableMember. J'ai longtemps pensé q'une option aurait permis de changer (autrement que dans le code) le type de liaison. Après m'être acharné sur cette idée, et une fouille approfondie des sources, j'ai découvert qu'il fallait utiliser un autre type "d'enregistrement" (terme à trouver) : Data.Bind.Components.RegisterValuePropertyName.
    Ceci pourrait faire l'objet d'une FAQ, quoique je ne soit pas sûr que ce soit une Question Fréquente

  7. #7
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    tient, j'ai fait un test rapide

    c'est un mélange de canvas et de composants qui peut s'adapter facilement en tout canvas

    le principe est de dessiner sur un bitmap tout le cadran, puis de l'afficher dans deux TImage qui scroll dans un layout en clipping

    Bousole.zip
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 633
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    le principe est de dessiner sur un bitmap tout le cadran, puis de l'afficher dans deux TImage qui scroll dans un layout en clipping
    Merci, cette technique servirait très bien dans le cadre d'une utilisation de style (FMX) dans un composant. Une piste que je n'ai pas encore creusée n'en étant pour l'instant qu'aux liaisons

  9. #9
    Membre émérite
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 139
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 139
    Billets dans le blog
    5
    Par défaut
    Bonjour à tous et bonne année

    C'est amusant mais je pensais compléter ma collection de composant avec un truc dans ce genre.

    Ce qu'il faut savoir avec les angles c'est que c'est un peu chiant à gérer en général il faut se fixer un domaine (0-360 ou -180 +180) et quelque soit la valeur entrée la remettre dans ce domaine. Après il faut gérer le problème des angles situés à proximité des limites extérieures du domaine.

    Ensuite pour ce qui est de l'affichage j’essaie dans la mesure du possible de paramétrer au maximum pour que l'utilisateur puisse adapter au mieux l'affichage en fonction de son usage.
    Par exemple combien de degrés sont affiché dans ton rectangle, combien de degré représente une graduation...
    Ensuite pour ce qui est de l'affichage je dessine tout dans une bitmap que j'affiche ensuite dans mon rectangle.

  10. #10
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 633
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par Gouyon Voir le message
    Bonjour à tous et bonne année
    Meilleurs vœux

    C'est amusant mais je pensais compléter ma collection de composant avec un truc dans ce genre.
    en fait c'est parce-que la liaison que je t'avais proposé aux départ pour tes composants était bidirectionnelle que je me suis lancé le défi de fin d'année

    Ensuite pour ce qui est de l'affichage j’essaie dans la mesure du possible de paramétrer au maximum pour que l'utilisateur puisse adapter au mieux l'affichage en fonction de son usage.
    Par exemple combien de degrés sont affiché dans ton rectangle, combien de degré représente une graduation...
    ça, c'est une étape que je n'avais bien sûr pas encore franchie : les propriétés, bien sûr que je le ferai quand il s'agira d'écrire l'unité composant. La question était plus sur la gestion des angles (chiante) d'ArcDial qu'autre chose

    Ensuite pour ce qui est de l'affichage je dessine tout dans une bitmap que j'affiche ensuite dans mon rectangle.
    Oui, j'ai regardé tes sources la technique proposée par Paul est une solution, envisageable même en tant que style (juste avant le réveillon j'ai même entraperçu comment faire )

Discussions similaires

  1. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  2. Réponses: 4
    Dernier message: 05/06/2002, 14h35
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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