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

Langage Delphi Discussion :

Comment faire pour copier un objet avec ses descendants ?


Sujet :

Langage Delphi

  1. #1
    Membre habitué Avatar de bs.box
    Inscrit en
    Mai 2008
    Messages
    174
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 174
    Points : 173
    Points
    173
    Par défaut Comment faire pour copier un objet avec ses descendants ?
    Voila, j'ai un TPANEL qui groupe (des TButton; TEdit; ..), et je veut instancier un nouveau TPanel d'une manière dynamique, sachant que le groupe des objects que je veut copier est VISIBLE !! sur ma forme.

    Alors, y'a t'il une idée, ou bien Comment faire pour copier cet objet qui regroupe des sous objects avec les mêmes caractéristiques?
    ______________________________________________________________________
    Le sketch qui m'a marqué le plus! écoutez les programmeurs : Site de Yan Marchal

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Vous dites vouloir copier toute les caractéristiques ...

    Est-ce qu'un pointeur peut faire l'affaire? (toujours sur le même objet)

    Est-ce que le contenu de ces panels peuvent changer?(3 edits sur le premier et 4 edits sur le deuxième)?

    Sinon, commencez par vous créer une structure contenant tout les objets que vous avez besoin.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    TMonPanel = record
      Edit1     : TEdit;
      Edit2     : TEdit;
      Button1 : TButton;
    end;
    ensuite vous pourrez copier d'une structure à l'autre les propriétés de vos objets

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Panel1 : TMonPanel //en supposant que c'est votre objet original
    Panel2 : TMonPanel
     
    Panel2.Edit1 := TEdit.Create(self);
    Panel2.Edit1.Text = Panel1.Edit1.Text;
    Très lourd à programmer mais cela fonctionnera.

    Dans quel but voulez vous faire cela?

    Car il existe aussi les Frames en delphi...

    "Peut-être" aussi avec Assign cela pourrait facilité la tâche mais personnellement, je n'ai jamais expérimenté.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Désolé j'ai oublié de mentionné un truc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PanelCopie := TPanel.Create(self);
    Dans la structure panel2

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Panel2.Edit1 := TEdit.Create(PanelCopie);
    Panel2.Edit1.Parent := PanelCopie;
    Panel2.Edit1.Text = Panel1.Edit1.Text;

  4. #4
    Membre habitué Avatar de bs.box
    Inscrit en
    Mai 2008
    Messages
    174
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 174
    Points : 173
    Points
    173
    Par défaut
    d'aprés:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    TMonPanel = record
      Edit1     : TEdit;
      Edit2     : TEdit;
      Button1 : TButton;
    end;
    ensuite vous pourrez copier d'une structure à l'autre les propriétés de vos objets

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Panel1 : TMonPanel //en supposant que c'est votre objet original
    Panel2 : TMonPanel
     
    Panel2.Edit1 := TEdit.Create(self);
    Panel2.Edit1.Text = Panel1.Edit1.Text;
    et :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PanelCopie := TPanel.Create(self);
    Je crois qu'il y'a confusion.. oubien j'ai mal interprété votre réponse,
    Car tu t'oublie que "TMonPanel" est un "RECORD" !!
    puis tu fait: "PanelCopie := TPanel.Create(self);" sinon je vois pas l'utilité
    de "type TMonPanel=Record"

    Je doit expliquer que je recherche une manière de faire cela dynamiquement,
    veux dire lors de l'éxécution du programme, car je ne vois pas comment faire si le panel que je doit copier peut avoir des "TEdit" comme il ne peut pas contenire ces EDITS ou autres objects?!.

    En tout cas ce qui concèrne la solution de faire une structure comme vous expliquer, j'ai déja appliqué ça autrement,
    Ex:

    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
    procedure ClickPROC;
    begin
    //-> l'évennement onclick
    ShowMessage('Clique du bouton :'+#13+
                         TWinControl(Form1.ActiveControl).Name
                       )
    end;
     
    procedure CreatePANEL(Const Num:TCaption);
    var Panel:TPanel;
         Edit:TEdit;
         Button:TButton;
    begin
     Panel:=TPanel.Create(nil);
     Panel.Name:='Panel'+Num;
     Form1.InsertControl(Panel); // Où Form1 est la forme qu'on veut instancier avec..
     with Panel do
     begin
     width:=100;
     ..
     end;
     Edit:=TEdit.Create(nil);
     Edit.Name:='Edit'+Num;
     Form1.InsertControl(Edit);
     with Edit do
     Edit.Parent:=Panel;
     begin
     width:=100;
     ..
     end;
     Button:=TButton.Create(nil);
     Button.Name:='Button'+Num;
     Form1.InsertControl(Button);
     with Button do
     begin
     Button.Parent:=Panel;
     width:=100;
     @OnClick:=@ClickPROC
     ..
     end;
    end;
    Enfin presque, mais en tout cas merci de répondre.
    a+
    ______________________________________________________________________
    Le sketch qui m'a marqué le plus! écoutez les programmeurs : Site de Yan Marchal

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    Oulah c'est bien compliqué tout ça. Essayez plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function CopieComponents( ASource: TComponent; AOwner, AParent: TComponent ): TPanel;
    var
     Cpt: Integer;
    begin
      Result := TComponentClass(ASource.ClassType).Create( ASource.Owner );
      Result.Assign( ASource );
      if Result is TControl then
        TControl(Result).Parent := AParent;
      for Cpt := 0 to ASource.ComponentIndex - 1 do
        CopieComponents( ASource.Components[Cpt], AOwner, Result );
    end;
    Et dans l'appel faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.ButtonClick1(Sender: TObject);
    var
      PanelCopie: TPanel;
    begin
      PanelCopie := CopieComponents( PanelACopier, Self, CompoParent );
    end;
    Où PanelACopier est le TPanel à recopier et CompoParent le composant devant servir de parent visuellement au niveau panel créé.
    La FAQ - les Tutoriels - Le guide du développeur Delphi devant un problème

    Pas de sollicitations techniques par MP -

  6. #6
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Juste pour faire mon habituel emm.. quiquineur, il ne s'agit pas de copier un objet et ses descendants, mais un composant visuel et ses enfants.

    Bon, ceci étant précisé, c'est une question qui m'a l'air de revenir assez souvent, quand on a un ensemble de composants à reproduire, il existe une méthode alternative pour ça : l'utilisation de TFrame.

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    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 460
    Points : 24 874
    Points
    24 874
    Par défaut
    Dans la Boucle For sur ComponentIndex, cela Assign des TControl divers à des TPanels ... ça cloche ... non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function CopieComponents( ASource: TComponent; AOwner, AParent: TComponent ): TComponent;
    var
     Cpt: Integer;
    begin
      Result := TComponentClass(ASource.ClassType).Create( ASource.Owner );
      Result.Assign( ASource );
      if Result is TControl then
        TControl(Result).Parent := AParent;
      for Cpt := 0 to ASource.ComponentIndex - 1 do
        CopieComponents( ASource.Components[Cpt], AOwner, Result );
    end;
    Pour les Frames, c'est la solution première, ou encore une Forme ne contenant que le Panel et ses boutons que l'on créé à volonté et que l'on ancre dans une autre forme, ...

    Et voir si l'on ne pourrait pas bidouiller un truc avec les Stream et Write\ReadComponent ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function CopyComponent(AComponent: TComponent; AOwner: TComponent = nil): TComponent;
    var
      BinStream: TMemoryStream;
    begin
      BinStream := TMemoryStream.Create;
      try
        BinStream.WriteComponent(AComponent);
        BinStream.Seek(0, soFromBeginning);
        Result := TComponentClass(AComponent.ClassType).Create(AOwner);
        BinStream.ReadComponent(Result); // Problème de Nommage ...
     finally
        BinStream.Free();
      end;
    end;
    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

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    Par défaut
    Alors, y'a t'il une idée, ou bien Comment faire pour copier cet objet qui regroupe des sous objects avec les mêmes caractéristiques?
    Une solution propre : créer un objet descendant de TFrame, qui fait tout ce que tu veux, et l'instancier autant de fois que tu le veux dans ton code. Autrement dit, héritage + instanciation
    "It's more fun to compute !"

  9. #9
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Dans la Boucle For sur ComponentIndex, cela Assign des TControl divers à des TPanels ... ça cloche ... non ?
    Oups en effet c'était un reste de ma première idée avant que je transforme ma fonction en une version générique. Merci de m'avoir pointé cette erreur, je corrige dans mon précédent message.
    La FAQ - les Tutoriels - Le guide du développeur Delphi devant un problème

    Pas de sollicitations techniques par MP -

  10. #10
    Membre habitué Avatar de bs.box
    Inscrit en
    Mai 2008
    Messages
    174
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 174
    Points : 173
    Points
    173
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function CopieComponents( ASource: TComponent; AOwner, AParent: TComponent ): TComponent;
    var
     Cpt: Integer;
    begin
      Result := TComponentClass(ASource.ClassType).Create( ASource.Owner );
      Result.Assign( ASource );
      if Result is TControl then
        TControl(Result).Parent := AParent;
      for Cpt := 0 to ASource.ComponentIndex - 1 do
        CopieComponents( ASource.Components[Cpt], AOwner, Result );
    end;
    Les problèmes qui sont engendrés sont:
    1) Exception : Can't assign TPanel to TPanel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      Result.Assign( ASource );
    2) Delphi ne me permette pas d'affecter "AParent"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      if Result is TControl then
        TControl(Result).Parent := AParent;
    * Seulement si j'ajoute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      if Result is TControl then
        TControl(Result).Parent := TWinControl(AParent);
    L'autre solution du copiage engendre le problème de nommage comme
    vous avez dit; seulement s'il y'aura une idée de faire ce travail..

    En tout cas merci d'intervenire..
    ______________________________________________________________________
    Le sketch qui m'a marqué le plus! écoutez les programmeurs : Site de Yan Marchal

  11. #11
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    Voilà un début de solution
    Vue texte de la fiche
    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
    object Form1: TForm1
      Left = 198
      Top = 124
      Width = 870
      Height = 500
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -13
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 120
      TextHeight = 16
      object Panel1: TPanel
        Left = 0
        Top = 0
        Width = 401
        Height = 57
        TabOrder = 0
        object Button1: TButton
          Left = 16
          Top = 16
          Width = 75
          Height = 25
          Caption = 'Button1'
          TabOrder = 0
          OnClick = Button1Click
        end
        object Edit1: TEdit
          Left = 264
          Top = 16
          Width = 121
          Height = 24
          TabOrder = 1
          Text = 'Edit1'
        end
      end
      object Button2: TButton
        Left = 416
        Top = 32
        Width = 75
        Height = 25
        Caption = 'Button2'
        TabOrder = 1
        OnClick = Button2Click
      end
    end
    Code de la fiche
    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
    unit ex01a;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        Panel1: TPanel;
        Button1: TButton;
        Button2: TButton;
        Edit1: TEdit;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      Pos_Top_panel : Integer ;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with TButton(Sender).Parent as TPanel do
        caption := TimeToStr(now) ;
    end;
     
     
    function ComponentToString (Component: TComponent): string;
    var
      BinStream:TMemoryStream;
      StrStream: TStringStream;
      st1: string;
    begin
      st1:= '' ;
      BinStream := TMemoryStream.Create;
      try
        StrStream := TStringStream.Create(st1);
        try
          BinStream.WriteComponent(Component);
          BinStream.Position := 0 ;
          ObjectBinaryToText(BinStream, StrStream);
          StrStream.Position := 0 ;
          Result:= StrStream.DataString;
        finally
          StrStream.Free;
        end;
      finally
        BinStream.Free
      end;
    end;
     
    function StringToComponent(Value: string): TComponent;
    var
      StrStream:TStringStream;
      BinStream: TMemoryStream;
    begin
      StrStream := TStringStream.Create(Value);
      try
        BinStream := TMemoryStream.Create;
        try
          ObjectTextToBinary(StrStream, BinStream);
          BinStream.Position := 0 ;
          Result := BinStream.ReadComponent(nil);
        finally
          BinStream.Free;
        end;
      finally
        StrStream.Free;
      end;
    end;
     
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      st1 : string ;
      i1 : integer ;
      cp1 : TComponent ;
      panelX : TPanel ;
    begin
      panelX := TPanel(StringToComponent(ComponentToString(Panel1))) ;
      Pos_Top_panel := Pos_Top_panel + Panel1.Height ;
      panelX.Top := Pos_Top_panel ;
      panelX.Parent := form1 ;
      for i1:=0 to Panel1.ControlCount-1 do
      begin
        st1 := ComponentToString(Panel1.controls[i1]) ;
        cp1 := StringToComponent(st1) ;
        if cp1 is TButton  then
        begin
          with cp1 as TButton do
            Parent := panelX ;
          TButton(cp1).OnClick := Button1Click ;
        end ;
        if cp1 is TEdit  then
          with cp1 as TEdit do
            Parent := panelX ;
      end ;
    end;
     
    initialization
      RegisterClasses([TPanel]) ;
      RegisterClasses([TButton]) ;
      RegisterClasses([TEdit]) ;
    end.

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    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 460
    Points : 24 874
    Points
    24 874
    Par défaut
    Effectivement, ALWEBER, j'avais proposé aussi la solution Stream et Write\ReadComponent ... tu n'as le problème est le nommage des composants genre "Un composant 'Button1' existe déjà"
    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

Discussions similaires

  1. Réponses: 10
    Dernier message: 18/04/2011, 15h53
  2. Réponses: 12
    Dernier message: 14/04/2009, 20h10
  3. [E-03] Comment faire pour qu'un objet s'enfuie quand la souris approche
    Par moilou2 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 25/03/2009, 16h52
  4. Réponses: 9
    Dernier message: 09/03/2007, 15h01
  5. Réponses: 3
    Dernier message: 03/02/2007, 00h12

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