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 :

PageControl.[PageControl.PageCount-1].free en erreur


Sujet :

Langage Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut PageControl.[PageControl.PageCount-1].free en erreur
    Bonjour,

    J'ai un PageControl avec 2 onglets "fixes"
    Je créé dynamiquement des pages supplémentaires au besoin. Cela fonctionne parfaitement

    Quand je clique sur l'onglet créé et que je veux le détruire j'utilise la procédure suivante et cela fonctionne parfaitement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TLettre.SupprimeOngletClick(Sender: TObject);
    begin
        if PageControl1.ActivePageIndex > 1
        then begin
            PageControl1.Pages[PageControl1.ActivePageIndex].Free;
        end;
    end;
    Dans mon FormCloseQuery je souhaite détruire tous les onglets créés dynamiquement avant de fermer la fenêtre
    j'utilise la procédure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        While PageControl1.PageCount>2 do
           PageControl1.Pages[PageControl1.PageCount-1].Free;
    Et là j'ai une méchante erreur dès le 1er passage "violation d'accès"

    Vous voyez un truc que je ne vois pas ?

  2. #2
    Membre extrêmement actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2017
    Messages
    1 990
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2017
    Messages : 1 990
    Points : 6 237
    Points
    6 237
    Par défaut
    Tu devrais vérifier la chronologie des évènements: Est-ce que ta page ne serait pas fermée AVANT que tu essaies de détruire tes onglets?

  3. #3
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Ben je suis dans le CloseQuery qui survient avant le FormClose, donc la fiche est toujours là et je ne détruit rien avant
    En suivant les variables, j'ai pageCount = 3 au départ et j'ai encore PageCount = 3 dans la boucle ... comprends pas ce qu'il se passe ...

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    il manque des infos dans tes explications

    voici un test qui fonctionne avec 1 PageControl et 3 boutons sur une 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
     
    unit Unit1;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
     
    type
      TForm1 = class(TForm)
        PageControl1: TPageControl;
        Button1: TButton;
        Button2: TButton;
        TabSheet1: TTabSheet;
        Button3: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
        procedure Button3Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      T: TTabSheet;
    begin
      T := TTabSheet.Create(PageControl1);
      T.PageControl := PageControl1;
      T.Caption := 'TabSheet' + IntToStr(PageControl1.PageCount);
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
       while PageControl1.PageCount > 2 do
         PageControl1.Pages[PageControl1.PageCount-1].Free;
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      Application.Terminate;
    end;
     
    procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin
      while PageControl1.PageCount>2 do
        PageControl1.Pages[PageControl1.PageCount-1].Free;
      CanClose := False;
    end;
     
    end.

  5. #5
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Bonjour Paul TOTH,
    Merci de te pencher sur mon soucis.

    La seule différence que je vois avec mon code c'est le CanClose = false dans ton FormCloseQuery
    Mais j'ai toujours cette erreur quand je ferme ...

    J'ai refait un projet avec ton code qui est bien sur ok

    (Bon j'ai quand même appris que même avec Application.Terminate on passe par le FormCloseQuery et donc le close). Je pensais qu'on "plantait" volontairement l'appli.

    Je cherche ...

  6. #6
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Bon ... J'ai trouvé mais je suis perplexe ...

    Dans mon programme je déclare une TStringList nommée Lettre_RowSelect. Elle ne se remplit pas automatiquement, je dois cliquer sur des boutons pour le faire.

    Dans mon FormCloseQuery j'ai ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TLettre.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin
        if Assigned(Lettre_RowSelect)
        then FreeAndNil(Lettre_RowSelect);
     
        While PageControl1.PageCount>2 do
           PageControl1.Pages[PageControl1.PageCount-1].Free;
    end;
    Il plante donc dans la ligne du PageControl1.Pages[PageControl1.PageCount-1].Free; mais si je supprime les lignes pour libérer Lettre_RowSelect ça fonctionne!

    Du coup ... j'ai inversé les lignes, je supprime mes pages puis je détruit la StringList si elle est créé et ... ça fonctionne !

    Mais pourquoi ? les 2 ne sont pas liées ... ???

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    j'ai pris ma boule de cristal, et j'ai vu que tu avais un code dans PageControl.OnChange (ou OnChanging) qui tripatouille Lettre_RowSelect...ou quelque chose de ce genre, la vision est trouble.

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    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 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Question con !
    A quoi ça sert ?

    Si le Owner de PageControl1 est l'instance de TLettre, à la fermeture de cette fenêtre, les onglets seront libérés parce que PageControl1 est leur parent, au pire libérer parce que TLettre est le Owner des TTabSheet, cela dépend de votre code d'instanciation.
    Ou alors le OnClose fait une action caHide et l'on en revient à l'autre sujet qui montrait un cycle de vie de fenêtre mal maitrisée.

    Si TLettre était libérée, tout cela serait géré naturellement sans code sans devoir écrire tout ça.

    Et libérer des Onglets dans OnCloseQuery est une erreur, c'est dans OnClose qu'il faudrait le faire au pire en cas d'action caHide.
    OnCloseQuery c'est pour demander l'autorisation de fermer la fenêtre
    OnClose c'est lors de la fermeture de la fenêtre
    OnDestroy c'est lors de la destruction de la fenêtre

    l'autre approche c'est de retirer la page uniquement sans la libérer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      while PageControl1.PageCount > 2 do
        PageControl1.Pages[PageControl1.PageCount-1].PageControl := nil;
    Ensuite selon votre façon de faire TTabSheet.Create, c'est le Onwer ou votre code qui assurera la libération, peut-être une TObjectList pour gérer les onglets de façon plus fiable.
    N'est-ce pas logique ?
    C'est votre code qui instancie les TTabSheet, il semble que cela soit plus élégant que votre code assure la libération
    Indispensable lorsque l'on ne connaît pas par-cœur tous les mécanismes de libération par Owner et Parent.

    Même si libérer TLettre et l'instancier à chaque fois que nécessaire est bien plus simple.
    Et je reste convaincu que cette VA est un symptôme d'un problème d'instance ailleurs.

  9. #9
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Paul TOTH
    j'ai pris ma boule de cristal, et j'ai vu que tu avais un code dans PageControl.OnChange (ou OnChanging) qui tripatouille Lettre_RowSelect...ou quelque chose de ce genre, la vision est trouble.
    C'est là qu'on voit les experts! Oui, c'est vrai que j'ai un OnChange ... et que dedans je tripatouille le Lettre_RowSelect
    Je commence à comprendre ...

    ShaiLeTroll
    Question con !
    Oui je sais ... je suis un spécialiste mais dans mon métier, elles détectent souvent des problèmes

    A quoi ça sert ?
    Ben, j'ai lu qu'il fallait toujours libérer les objets créés dynamiquement à cause des fuites mémoires. Du coup je détruit tout ce que je crée.

    Indispensable lorsque l'on ne connaît pas par-cœur tous les mécanismes de libération par Owner et Parent.
    Ensuite selon votre façon de faire TTabSheet.Create, c'est le Onwer ou votre code qui assurera la libération, peut-être une TObjectList pour gérer les onglets de façon plus fiable.
    Dans le code, je crée les onglets comme ceci en utilisant le Self et franchement sans savoir ce que c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    procedure TLettre.AjouteGrilleClick(Sender: TObject);
    Var
        Tbs: TTabSheet;
    begin
        Tbs := TTabSheet.create(Self);
        Tbs.PageControl := PageControl1;
    end;
    Là je me rends compte que j'ai une grosse lacune.
    Parent : je comprends que c'est celui qui contient visuellement le controle (fiche, composant ...)
    Owner ... propriétaire ... Comment on sait qui est le Owner ? ... par le create ...
    Et quand on crée l'onglet qui est le Owner ? en fait je me rends compte que je ne me suis jamais soucié du Owner ...
    Dans le .create(Self) ... c'est qui self ?
    il y a un tuto quelque part qui pourrait m'expliquer ça ? J'ai trouvé des trucs mais ...

    J'ai essayé pour voir de changer le .create
    Tbs := TTabSheet.create(PageControl1);
    Tbs := TTabSheet.create(Lettre);
    Je n'ai rien vu comme changement, mais j'imagine qu'il y a en un ... mais lequel ?

    Si TLettre était libérée, tout cela serait géré naturellement sans code sans devoir écrire tout ça.
    Tlettre est créé dans le source, je n'ai pas encore tenté de créer tout ça au fur et à mesure de l'utilisation des fiches.
    Ça va venir ... mais pour le moment je reste prudent
    Du coup, quand la fiche se ferme, elle libère les composants créés dynamiquement ? Pas besoin de les supprimer ?

    Et libérer des Onglets dans OnCloseQuery est une erreur, c'est dans OnClose qu'il faudrait le faire au pire en cas d'action caHide.
    OnCloseQuery c'est pour demander l'autorisation de fermer la fenêtre
    OnClose c'est lors de la fermeture de la fenêtre
    Ok, j'avais lu qu'il valait mieux faire les enregistrement et autres manip avant le onClose ...

    Le post tourne autour du Owner et Parent ...

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    ouch...ça montre un grand manque de bases

    j'ai un vieille article là dessus ici http://tothpaul.free.fr/tips.php?pv_class

    Self, c'est une notion objet de base :
    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
     
    type
      TMonObject = class
        procedure test;
      end;
     
    var
      o: TMonObject;
     
    procedure TMonObject.test;
    begin 
      if Self = o then
       ShowMessage('je suis o !')
      else
       ShowMessage('je ne suis pas o !');
    end;
     
    begin
      o := TMonObject.Create; // je crée un objet o
      o.test; // il me dit qu'il est o
    end;
    dans cet exemple on voit que je peux créer un objet "o", et que la variable Self est un pointeur vers "moi-même", donc l'objet o

    dans ton code tu écris "Tbs := TTabSheet.create(Self);" Self c'est donc tout simplement l'instance courante de TLettre, et peu importe s'il existe une variable globale "L := TLettre.Create", Self me donne accès à "moi-même" sans que j'ai besoin de connaître le nom de cette variable.

    Ensuite le parent contient sont enfant visuellement, le Propriétaire (Owner) possède l'objet, notamment pour un objet non visuel (TDataSet)...un objet visuel à donc à la fois un Parent et un Owner...les deux le détruisent automatiquement quand ils sont détruits.

    donc TLettre étant parent et propriétaire, il y a deux bonnes raisons pour que les TabSheet soient détruites automatiquement quand la fiche est détruite.

    > Ben, j'ai lu qu'il fallait toujours libérer les objets créés dynamiquement à cause des fuites mémoires. Du coup je détruit tout ce que je crée.
    Oui, mais il y a plusieurs façon de détruire un objet; lui associer un parent et/ou un owner est une des solutions

  11. #11
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    ouch...ça montre un grand manque de bases
    Oui effectivement, je suis tombé sur Delphi par hasard : un jour je bossais (mon domaine c'est la gestion et le contrôle de gestion) chez un client, son logiciel de facturation était sous environnement Pick et il fallait reprendre un grand nombre d'info dans un cahier à la mano. Ca ma gonflé (perte de temps très importante et pour rien), et j'ai proposé à l'entreprise de reprendre le système. J'ai développé vite fait un programme en VBasic, et le logiciel a mis 10 minutes à s'allumer! Il fallait que je trouve un langage plus rapide et relativement facile moi qui ne vient pas du monde informatique. Le hasard d'une rencontre m'a mis sur le chemin de Delphi 3 qui était en promo avec la version 1 ... puis la 7 ... puis ... nous étions en 1995 (modem à 33000 baud il me semble ... et internet ...) quelque chose comme ça. Depuis je satisfais mes besoins en traitement avec cet environnement.

    Donc, si l'on peut me conseiller un ouvrage qui serait pas trop basique mais fondamental, je prends avec plaisir

    Et puisqu'on en est aux confidences, je tiens à remercier tous les acteurs de ce forum pour leur gentillesse (bon parfois les experts te font sentir que là tu déconnes, mais ... ce sont les experts, on est pareil, chacun dans son domaine )
    Merci Paul TOTH, SailLeTroll, SergioMaster et vous tous qui, avec bienveillance et patience, m'accompagnez dans ma compréhension de ce langage. Et si vous me connaissiez, vous sauriez que ces remerciements ne sont pas feints.

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

Discussions similaires

  1. [Dev-Pascal] [Free Pascal] Erreurs de compilation avec Link.res
    Par swayly dans le forum Autres IDE
    Réponses: 7
    Dernier message: 16/03/2008, 01h37
  2. Réponses: 8
    Dernier message: 05/02/2007, 09h56
  3. [Free Pascal] Erreur de compilation hallucinante
    Par molesqualeux dans le forum Free Pascal
    Réponses: 9
    Dernier message: 06/05/2006, 21h10
  4. [Free Pascal] Erreur lors de l'éxecution. (exitcode = 106)
    Par phoebos dans le forum Free Pascal
    Réponses: 2
    Dernier message: 03/03/2006, 22h24
  5. Erreur à l'assignation du PageControl sur une tab
    Par MarcP dans le forum Composants VCL
    Réponses: 1
    Dernier message: 08/08/2005, 22h49

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