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 :

Création de composant épisode 4


Sujet :

Composants FMX Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    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 658
    Billets dans le blog
    65
    Par défaut Création de composant épisode 4
    Bonjour,
    Je croyais mon composant TNameFileImage réglé mais, le fait d'avoir changé de poste, réinstallé Delphi etc.. suite au crash de mon défunt PC en testant à nouveau j'ai un problème RTTI

    Je dois convertir un string en TFileName et vice-versa pour cela j'ai écrit ce convertisseur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    initialization
     TValueRefConverterFactory.RegisterConversion(TypeInfo(String), TypeInfo(TFileImage), TConverterDescription.Create(
        procedure(const I: TValue; var O: TValue)
        begin
          if I.isType<String> then
           O := TFileName(I.ToString)
          else
           O := String(I.ToString);
          end,
          'NomFichierImageToString', 'NomFichierImageToString', EmptyStr, True, EmptyStr, nil)
        );
    finalization
     TValueRefConverterFactory.UnRegisterConversion(TypeInfo(String), TypeInfo(TFileImage));
    Mon problème je ne sais pas trop où mettre cette déclaration dans le partie (unité) design ou dans l'unité d'enregistrement (runtime ?)
    Actuellement dans la partie "design" le composant fonctionne très bien dans l'EDI par contre à l'exécution

    Erreur
    ---------------------------
    EvalError dans LinkControlToField1 : Incapable de trans-typer ou de trouver des convertisseurs entre les types string et TBitmap.
    Cela indiquerai donc qu'il faudrait que je mette cette déclaration dans la partie enregistrement j'ai tenté mais même punition ! sauf à indiquer dans ma liste des uses
    uses .., ImageFileFMX,regImageFileFMX; soit les deux unités (alors que quand je pose le composant seule l'unité ImageFileFMX se mette automatiquement)

    la bonne option semblerait donc de mettre ce convertisseur dans l'unité enregistrement. Sachant que le composant est dual framework VCL/FMX n'y aura t-il pas un soucis ?

    Mon soupçon se porte sur ma méthode de création de paquets, ne faudrait-il pas que je crée un paquet designtime et un paquet runtime ? c'est là où je sèche comment fait-on ça "proprement" (c.a.d. pour une installation facile) ?

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    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 658
    Billets dans le blog
    65
    Par défaut Relance du sujet
    Bonjour,

    Je pense avoir trouvé où mettre le convertisseur, du moins n'ai-je plus l'erreur d'incapacité de trans-typage !
    En fait, pour l'erreur, je cherchai un moyen de changer le type reconnu (TPicture pour VCL/TBitmap pour FMX), j'ai plutôt simplement changer la déclaration, au prix de l'ajout d'unité dans la liste des uses.

    Reste un souci , le dernier coup de collier avant de finaliser.

    Ce composant en VCL fonctionne parfaitement aussi bien au design qu'à l'exécution cependant en FMX (j'ai créé un composant qui accepte les deux frameworks) j'ai un problème à l'exécution avec la liaison rapide.

    Une vidéo valant mieux qu'un long discours (vous excuserez les clics )
    http://serge-girard.developpez.com/t...MX_edit_2.webm
    Il est rageant que je doive écrire : "Attention, vous devez absolument faire un lien manuel pour lier ce composant".

    Ma question est donc la suivante quelle différence entre le composant VCL et le FMX pourrait-il y avoir surtout que, à part la partie Register, c'est la même unité ImageFile.pas

    Question subsidiaire : Pour l'instant j'ai mis les procédures d'enregistrement/dé-enregistrements dans les sections initialization/finalization , je me demande s'il ne serait pas possible (pertinent) de les mettre dans les évènements OnCreate et OnDestroy du composant ?

    Merci à ceux qui auraient joué au jeu des 7 erreurs dans mes sources.
    PS. Je n'ai pas mis les projets tests, ni les sources deux .bpl, trop de dépendances avec des répertoires (installation) ou fichiers externes (images) m'en empêche pour l'instant
    Fichiers attachés Fichiers attachés

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    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 658
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    Eurêka ! Tout se joue dans le convertisseur, pas encore tout à fait au point puisqu'il va me falloir gérer l'exception du LoadFromFile mais c'est un détail après ces mois de galère
    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
     
      TValueRefConverterFactory.RegisterConversion(TypeInfo(String),
        {$IFDEF FMX} TypeInfo(TBitmap){$ELSE} TypeInfo(TPicture){$ENDIF},
        TConverterDescription.Create(
          procedure(const I: TValue; var O: TValue)
          begin
            if I.isType<String> then
             {$IFDEF FMX}
               TBitmap(O.AsObject).LoadFromFile(I.ToString)
             {$ELSE}
               TPicture(O.AsObject).LoadFromFile(I.ToString)
               // O:= TFileName(I.ToString)
             {$ENDIF}
            else
             O := String(I.ToString);
          end,
          Convertisseur,
          'ImageFile', EmptyStr, True,EmptyStr,
          nil
          )
        );
    Maintenant il va falloir que je comprenne pourquoi ce sont des TBitmap ou TPicture ( {$IFDEF FMX} TypeInfo(TBitmap){$ELSE} TypeInfo(TPicture){$ENDIF} ) qui sont "capturés" par la liaison de type TLinkControlToField et non la classe que j'ai créée
    et voir s'il n'y va pas y avoir des conséquences inattendues si je rajoute une liaison avec une image contenue dans un blob

    D'où la question du jour très "RTTI esque" comment retrouver le point de départ (mon composant) dans mon convertisseur ?

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    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 658
    Billets dans le blog
    65
    Par défaut Votre opinion
    Bonjour,

    voici plusieurs versions de mon convertisseur pour la partie VCL , d'après vous quelle est la plus adaptée, à moins qu'il y ait mieux ? Les RTTI et moi ce n'est que le début

    version 1 : la plus simple sans garde-fou
    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
     
    procedure RegisterConverter;
    begin
      if not TValueRefConverterFactory.HasConverter(Convertisseur) then
      begin
        TValueRefConverterFactory.RegisterConversion(TypeInfo(String),
          TypeInfo(TPicture),
          TConverterDescription.Create(
          procedure(const InValue: TValue; var OutValue: TValue)
          begin
             try 
                   TPicture(OutValue.AsObject).LoadFromFile(InValue.ToString); 
             except 
                 TPicture(OutValue.AsObject).Graphic := nil; 
             end;
          end,
          Convertisseur, 'U_VCLRunTime', EmptyStr, True, EmptyStr, nil));
      end;
    end;
    version 2 : inspirée de l'unité Vcl.Bind.DBEngExt
    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
     
    procedure RegisterConverter;
    begin
      if not TValueRefConverterFactory.HasConverter(Convertisseur) then
      begin
        TValueRefConverterFactory.RegisterConversion(TypeInfo(String),
          TypeInfo(TPicture),
          TConverterDescription.Create(
          procedure(const InValue: TValue; var OutValue: TValue)
          var LOutObject : TObject;
          begin
              LOutObject := OutValue.AsObject;
              Assert(LOutObject <> nil);
              Assert(LOutObject is TPicture);
              TPicture(LOutObject).Graphic := nil;
              Assert(InValue.IsEmpty);  // cette assertion est la plus gênante, Utile ?  
              try TPicture(LOutObject).LoadFromFile(InValue.ToString); except end;
          end,
          Convertisseur, 'U_VCLRunTime', EmptyStr, True, EmptyStr, nil));
      end;
    end;
    version 3 idem mais avec FileExists (utile ?)
    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
     
    procedure RegisterConverter;
    begin
      if not TValueRefConverterFactory.HasConverter(Convertisseur) then
      begin
        TValueRefConverterFactory.RegisterConversion(TypeInfo(String),
          TypeInfo(TPicture),
          TConverterDescription.Create(
          procedure(const InValue: TValue; var OutValue: TValue)
          var LOutObject : TObject;
          begin
              LOutObject := OutValue.AsObject;
              Assert(LOutObject <> nil);
              Assert(LOutObject is TPicture);
              TPicture(LOutObject).Graphic := nil;
              Assert(FileExists(InValue.ToString));  // Utile ?
              try TPicture(LOutObject).LoadFromFile(InValue.ToString) except end; // cela peut ne pas être un format image connu
          end,
          Convertisseur, 'U_VCLRunTime', EmptyStr, True, EmptyStr, nil));
      end;
    end;

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    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 658
    Billets dans le blog
    65
    Par défaut Besoin de Testeurs
    Re,

    Voici donc les sources du composant dual (c'est-à-dire aussi bien VCL que FMX)
    J'ai besoin de testeurs pour :
    1- Savoir si le zip contient le nécessaire (voire du superflu).
    2- Savoir si vous réussissez à l'installer.
    3- Savoir si le comportement est correct.

    Je rappelle l'objectif : lier (LiveBindings) une Image à une chaine (chemin et nom de l'image) que cette chaine soit une simple zone de saisie (ce que je n'ai que peu testé), soit un combobox (mes tests android), soit une colonne dans une table comme dans cet exemple :
    Nom : Souhait.PNG
Affichages : 349
Taille : 209,7 Ko

    Cette dernière version est compilée avec RIO 10.3.1 mais j'avais commencé le composant avec TOKYO (Oui, j'ai galéré un an avant de trouver enfin de quoi il retournait !)
    Reste que je n'ai aucun moyen, de tester tout ce qui concerne les produits du pommier

    N.B. Il y a encore du "déchet" dans les sources du composant (en particulier dans les unités Regxxxxx) la déclaration les convertisseurs y sont totalement inutiles
    Fichiers attachés Fichiers attachés

  6. #6
    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
    j'ai lu en diagonal, mais si je comprend bien tu ajoutes à LiveBinding la conversion d'un String en image par un LoadFromFile, c'est donc en Runtime, puisque ce doit être possible à l'exécution (le DesignTime c'est pour ce qui se fait dans l'IDE, éditeur de propriété par exemple).

    la version 3 est mieux, mais les assertions sont des contrôles du code que l'on place pour vérifier que ce qu'on pense être le cas l'est bien...Et une option de compilation permet de supprimer toutes les assertions, c'est donc un outil de débogage.

    dès lors le FileExists ne devrait pas être une assertion mais une condition au chargement de l'image (ce qui est aussi gérée par le try/except de toute façon)

    les deux autres Assert sont des bretelles puisqu'on précise dans le RegisterConversion qu'on a affaire à un TPicture, on a donc théroriquement "LOutObject <> nil" et "LOutObject is TPicture", d'ailleurs le premier est superflus car nil n'est pas un TPicture; mais c'est bien l'objet d'une assertion de vérifier que ce qu'on pense vrai l'est bien.

    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
     
    procedure RegisterConverter;
    begin
      if not TValueRefConverterFactory.HasConverter(Convertisseur) then
      begin
        TValueRefConverterFactory.RegisterConversion(TypeInfo(String),
          TypeInfo(TPicture),
          TConverterDescription.Create(
          procedure(const InValue: TValue; var OutValue: TValue)
          var LOutObject : TObject;
          begin
              LOutObject := OutValue.AsObject;
              Assert(LOutObject <> nil);
              Assert(LOutObject is TPicture);
              TPicture(LOutObject).Graphic := nil;
              if FileExists(InValue.ToString) then
                try TPicture(LOutObject).LoadFromFile(InValue.ToString) except end; // cela peut ne pas être un format image connu
          end,
          Convertisseur, 'U_VCLRunTime', EmptyStr, True, EmptyStr, nil));
      end;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

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

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