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 :

Perte de focus / creation-suppresion runtime


Sujet :

Composants FMX Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10
    Points : 17
    Points
    17
    Par défaut Perte de focus / creation-suppresion runtime
    Bonjour à tous,

    En testant la création de compo visuel, je rencontre un problème que je n'avais pas en VCL.

    Contexte : création à la volée d'un objet visuel comportant un bouton pour se "détruire" . 1 gridpanellayout (addrow) contenant 2 Ttext, sur le premier TText un bouton en alignement haut/droit

    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
     
     TTickerMeteo = class(TPanel)
        private
        GridPanelLayout1: TGridPanelLayout;
        TextTownName: TText;
        TextTempValue: TText;
        Button1: TButton;
        FTempValue: string;
        FTownName: string;
        procedure SetTownName(const Value: string);
        procedure SetTempValue(const Value: string);
        //procedure ClickButton(Sender : TObject);
        public
        constructor Create(AOwner: TComponent); override;
        destructor destroy();override;
        property TownName : string read FTownName write SetTownName;
        property TempValue : string read FTempValue write SetTempValue;
        procedure ClickButton(Sender : TObject);
      end;
    Le composant est hérité d'un TPanel, oui pourquoi? bah pourquoi pas...

    le create :
    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
    constructor TTickerMeteo.Create(AOwner: TComponent);
    var
      I: Integer;
    begin
    //init des objets
    inherited create(nil);
    Align := TAlignLayout.Client;
    Parent := TFMXObject(Aowner);
    //GridPanelLayout
     
    GridPanelLayout1 := TGridPanelLayout.Create(self);
    GridPanelLayout1.RowCollection.Clear;
    GridPanelLayout1.ColumnCollection.Clear;
     
    GridPanelLayout1.Margins.Left := 10;
    GridPanelLayout1.Margins.Top := 10;
    GridPanelLayout1.Margins.Right := 10;
    GridPanelLayout1.Margins.Bottom := 10;
    GridPanelLayout1.Align := TAlignLayout.Client;
    GridPanelLayout1.Parent := TFMXObject(AOwner);
    GridPanelLayout1.ExpandStyle := TGridPanelLayout.TExpandStyle.AddRows;
     
    TextTownName := TText.Create(self);
    TextTownName.Stretch := false;
    //TextCoinName.Width := 200;
    TextTownName.TextSettings.HorzAlign := TTextAlign.Center;
    TextTownName.TextSettings.VertAlign := TTextAlign.Center;
    TextTownName.Text := 'Town Name';
    TextTownName.Align := TAlignLayout.Client;
     
     
    TextTempValue := TText.Create(self);
    TextTempValue.Stretch := false;
    //TextCoinValue.Width := 200;
    TextTempValue.TextSettings.HorzAlign := TTextAlign.Center;
    TextTempValue.TextSettings.VertAlign := TTextAlign.Center;
    TextTempValue.Text := 'Temp Value';
    TextTempValue.Align := TAlignLayout.Client;
    //TextCoinValue.Parent := GridPanelLayout1;
     
     
    GridPanelLayout1.ColumnCollection.BeginUpdate;
    GridPanelLayout1.RowCollection.BeginUpdate;
     
     //Ajout TText
       with GridPanelLayout1 do
        begin
          ColumnCollection.Add;
          ColumnCollection.Items[0].SizeStyle := TGridPanelLayout.TSizeStyle.Percent;
          ColumnCollection.Items[0].Value := 100;
          RowCollection.Add;
          RowCollection.Items[0].SizeStyle := TGridPanelLayout.TSizeStyle.Percent;
          RowCollection.Items[0].Value := 50;
          RowCollection.Add;
          RowCollection.Items[1].SizeStyle := TGridPanelLayout.TSizeStyle.Percent;
          RowCollection.Items[1].Value := 50;
     
        end;
     
    TextTownName.Parent := GridPanelLayout1;
    TextTempValue.Parent := GridPanelLayout1;
     
    GridPanelLayout1.RowCollection.EndUpdate;
    GridPanelLayout1.ColumnCollection.EndUpdate;
     
     
    Button1 := TButton.Create(self);
    Button1.Align := TAlignLayout.None;
    Button1.Anchors := [TAnchorKind.akTop,TAnchorKind.akRight];
    Button1.Size.Height := 35;
    Button1.Size.Width := 35;
    Button1.parent := TextTownName;
    Button1.Position.X := TextTownName.Width-35;
    Button1.Position.y := 0;
    Button1.Text := 'X';
    Button1.OnClick := ClickButton;
     
    end;
    Sur la form principal 2 panel, 1 button, le bouton associé au panel en align top et le 2ème panel en align client.
    Sur le click du bouton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    tempTicker := TTickerMeteo.create(Panel2);
    tempTicker.Button1.OnClick := MyClick;
    et la procédure ClickButton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    self.BeginUpdate;
    TControl(Sender).Parent.Parent.DisposeOf;
    self.EndUpdate;
    Voilà tout semble fonctionner, mais après avoir créé un objet puis l'avoir détruit je perd le control sur la form (déplacer la fenêtre, agrandir, réduire, fermer) pour reprendre le control il faut recliquer sur le bouton...

    Merci d'avance.

    Pour Info Delphi 10.4.2 / Win10 64bits

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    J'ai eu ce même problème quand j'ai voulu ajouter des boutons "fermer" pour mes TabItems. Je présume donc qu'il s'agit du même phénomène, heureusement la communauté Delphi s'en est mélé.
    Il faudrait rechercher la discussion pour les explications (retrouvée ici)

    le code final
    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
    procedure TMainForm.CloseTab(Sender: TObject);
    var F : TForm;
    begin
     if not Datas.PeutFermer then Exit;  // équivalent d'un OnCloseQuery
    
     if TabControl1.TabIndex=TabControl1.TabCount-1 then TabControl1.Previous else TabControl1.Next;  // passage au prochain tabitem
    
     if Liste.TryGetValue(TButton(Sender).TagString,F) then // vérifie que la forme existe et la détruit
       F.Close;
    
     TTask.Run(
        procedure
        begin
          TThread.Synchronize(nil,
            procedure
            begin
             TButton(Sender).TagObject.DisposeOf;
             if TabControl1.TabIndex>TabControl1.TabCount-1
               then TabControl1.TabIndex:=TabControl1.TabCount-1
            end);
        end);
     Liste.Remove(TButton(Sender).TagString); // ôte la forme de la liste 
    end;
    L'important (en bleu) utiliser un thread pour la destruction
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10
    Points : 17
    Points
    17
    Par défaut
    It Works!!! Merci Sergio "Senseï" Master

  4. #4
    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
    Points : 3 611
    Points
    3 611
    Par défaut
    Le Thread.forceQueue() suffit, pas besoin d'ouvrir une tache puis la synchroniser.

    Le DisposeOf() n'est plus nécessaire depuis l'arrêt de ARC, un .Free() comme en VCL passe très bien.

    A noter quand même qu'un Free() dans un événement de l'objet que l'on veut supprimer peut déclencher des violations d'accès sur iOS, donc soumission en file d'attente d'une façon ou d'une autre obligatoire.

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    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 455
    Points : 24 867
    Points
    24 867
    Par défaut
    @SergioMaster et @pprem , le Release qui existait encore dans Seattle permettant de mettre un objet dans le Purgatoire en vue d'une libération différée, par quoi est-il remplacé en Sydney puisque Déprécié
    C'est exactement ce que fait ce Thread Synchronize, il fait juste différer le moment de suppression dans une autre itération de la boucle principale Run
    une autre technique serait de le gérer dans OnIdle via une petite liste ou référence ... le Synchronize étant lui aussi fait lors du Idle car l'application a le temps pour traiter ça
    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

  6. #6
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    @pprem le code était écrit avec la 10.3 d'où le DisposeOf. Le ForceQueue je ne connaissais pas, effectivement ce serait plus "propre"

    @shailetroll il y a quelques trucs qui m'ont toujours rendu "frileux" le OnIdle en fait partie, certainement par manque de connaissance.
    Pour ce qui est du DisposeOf plutôt que du Release était déjà déprécié en 10.3 (ARC oblige ?) il le resterait pour Sidney (malgré l'abandon d'ARC ?)
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

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

Discussions similaires

  1. perte de focus lors de la creation d'input text avec innerhtml
    Par arnobidul dans le forum Général JavaScript
    Réponses: 27
    Dernier message: 14/06/2006, 17h49
  2. Réponses: 9
    Dernier message: 02/02/2006, 15h46
  3. Comment détecter la perte de focus d'une fenêtre
    Par Leviathan_72 dans le forum Windows
    Réponses: 5
    Dernier message: 31/12/2005, 00h22
  4. excel -> test lors de la perte du focus d'une cellule
    Par greg778 dans le forum Macros et VBA Excel
    Réponses: 24
    Dernier message: 26/09/2005, 17h26
  5. [VB.NET] Perte de focus entre deux form
    Par toniolol dans le forum Windows Forms
    Réponses: 2
    Dernier message: 05/07/2005, 08h00

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