Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 5 sur 5
  1. #1
    Invité de passage
    Profil pro
    Inscrit en
    novembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2012
    Messages : 2
    Points : 1
    Points
    1

    Par défaut Problème avec ShowModal et CheckBox

    Bonjour,

    J'ai deux forms identiques (Form1 et Form2) qui changent chacune l'état d'une checkbox lorsqu'on click sur un bouton. Lorsque ces deux formes sont indépendantes, cela marche. Par contre, lorsque la Form2 appelle la Form1 par ShowModal, je ne peux plus changer l'état de la checkbox1 de la Form1 en appuyant sur le Bouton de la Form1. C'est comme si l'appel par ShowModal bloquait l'accès aux propriétés de la checkbox.

    Quelqu'un peut-il m'aider à comprendre cela ? Et comment résoudre ce problème?

    Merci

    Les codes des unit2 et unit1 sont les suivants:
    Code :
    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
    unit Unit2; 
    {$mode objfpc}{$H+}
    interface
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,unit1;
    type
     
      { TForm2 }
     
      TForm2 = class(TForm)
        Button1: TButton;
        CheckBox1: TCheckBox;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end; 
     
    var
      Form2: TForm2;
      MyForm:TForm1;
     
    implementation
     
    {$R *.lfm}
     
    { TForm2 }
     
    procedure TForm2.Button1Click(Sender: TObject);
    begin
    with Form2.CheckBox1 do
      begin
        if Checked=true then Checked:=False
        else Checked:=true;
      end;
      try
         MyForm := TForm1.Create(nil);
         MyForm.ShowModal;
      finally
         MyForm.Free;
      end;
    end;
     
    end.
    et la form 1
    Code :
    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
    unit Unit1; 
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
     
    type
     
      { TForm1 }
     
      TForm1 = class(TForm)
        Button1: TButton;
        CheckBox1: TCheckBox;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end; 
     
    var
      Form1: TForm1; 
     
    implementation
     
    {$R *.lfm}
     
    { TForm1 }
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with Form1.CheckBox1 do
      begin
        if Checked=true then Checked:=False
        else Checked:=true;
      end;
      end;
     
    end.

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro Yves Lemaire
    Biologiste ; Progr(amateur)
    Inscrit en
    mars 2005
    Messages
    2 221
    Détails du profil
    Informations personnelles :
    Nom : Homme Yves Lemaire
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : mars 2005
    Messages : 2 221
    Points : 4 914
    Points
    4 914

    Par défaut

    Quelles sont les options de création automatique des fiches ?

    Si Form1 est en création automatique, l'application exécute Form1:=TForm1.Create et Form1 référence cette fiche.

    Si Form1 n'est créée qu'en dynamique, la création se fait dans la fiche 2 par MyForm := TForm1.Create, et Form1 ne pointe sur rien (il devrait y avoir une violation d'accès).

    Donc la solution est de ne pas utiliser Form1 mais self, qui référence l'objet dans lequel se produit l'événement :
    Code :
    1
    2
    3
    4
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with self.CheckBox1 do Checked := not Checked; // le self peut être omis car dans la portée (procédure de TForm1)
    end;
    Delphi 5 Pro et Code Typhon 4.41 sous Win 7 64 bits - Code Typhon 4.50 sous Ubuntu 14.04 64 bits et 12.04 64 bits (VM)

  3. #3
    Expert Confirmé
    Avatar de Ph. B.
    Homme Profil pro Philippe
    Freelance
    Inscrit en
    avril 2002
    Messages
    1 329
    Détails du profil
    Informations personnelles :
    Nom : Homme Philippe
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : avril 2002
    Messages : 1 329
    Points : 3 994
    Points
    3 994

    Par défaut

    Bonjour,

    Il y a des horreurs dans ce code !
    On n'utilise pas la variable Form2 dans une méthode de la classe TForm2.
    On n'utilise Self, au pire on ne l'indique pas.
    Il en est de même pour Form1 dans une méthode de la classe TForm1 !
    Le jour où vous utilisez une autre variable pour cette classe, au mieux cela ne compile pas, pire à l'exécution vous aurez droit à une exception pour violation d'accès (la variable (=objet) n'est pas initialisée), pire du pire, cela va affecter une autre variable (= un autre objet) de cette même classe, au final un bug qui peut être difficile à identifier...

    Maintenant, j'aimerais bien voir le code du projet et comment sont appelées ces fiches...

    Voici un code remanié :
    Code :
    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
    unit Unit2; 
    {$mode objfpc}{$H+}
    interface
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,unit1;
    type
     
      { TForm2 }
     
      TForm2 = class(TForm)
        Button1: TButton;
        CheckBox1: TCheckBox;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end; 
     
    var
      Form2: TForm2;
      MyForm:TForm1;
     
    implementation
     
    {$R *.lfm}
     
    { TForm2 }
     
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      // with Form2.CheckBox1 do <= ERREUR !
      with Self.CheckBox1 do
      begin
        if Checked=true then Checked:=False
        else Checked:=true;
      end;
      // ce qui précède pourrait s'écrire plus simplement, comme suit
      // Self.CheckBox1.Checked := not Self.CheckBox1.Checked;
      //
      try
         MyForm := TForm1.Create(nil);
         MyForm.ShowModal;
      finally
         MyForm.Free;
      end;
    end;
     
    end.
    et la form 1
    Code :
    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
    unit Unit1; 
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
     
    type
     
      { TForm1 }
     
      TForm1 = class(TForm)
        Button1: TButton;
        CheckBox1: TCheckBox;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end; 
     
    var
      Form1: TForm1; 
     
    implementation
     
    {$R *.lfm}
     
    { TForm1 }
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      //with Form1.CheckBox1 do <= ERREUR !
      with Self.CheckBox1 do
      begin
        if Checked=true then Checked:=False
        else Checked:=true;
      end;
      // ce qui précède pourrait s'écrire plus simplement, comme suit
      // Self.CheckBox1.Checked := not Self.CheckBox1.Checked;
    end;
     
    end.
    Concernant le ShowModal, c'est le fonctionnement attendu !
    Une application dont une fiche est affichée via un ShowModal voit ses autres fiches désactivées (au niveau de l'interface graphique) et ce tant que la fiche en question n'est pas fermée...

    Si vous voulez que les 2 fiches restent actives, il faut utiliser Show, mais ATTENTION, le code de gestion de l'événement OnClick du Button1 doit être revu. la fiche MyForm ne doit être créée que lors du 1° appel et pas des suivants, sa libération doit se faire lors de la fermeture de la fiche parente. Le code de la fiche Form2 ressemblerait à :
    Code :
    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
    unit Unit2; 
    {$mode objfpc}{$H+}
    interface
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,unit1;
    type
     
      { TForm2 }
     
      TForm2 = class(TForm)
        Button1: TButton;
        CheckBox1: TCheckBox;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
        MyForm:TForm1;
      public
        { public declarations }
      end; 
     
    var
      Form2: TForm2;
     
    implementation
     
    {$R *.lfm}
     
    { TForm2 }
     
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      Self.CheckBox1.Checked := not Self.CheckBox1.Checked;
     
      if not Assigned(MyForm) then
         MyForm := TForm1.Create(Self); // <= la fiche parente est alors chargée de la libération de cette fiche...
      MyForm.Show;
    end;
     
    end.
    Philippe.

  4. #4
    Invité de passage
    Profil pro
    Inscrit en
    novembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2012
    Messages : 2
    Points : 1
    Points
    1

    Par défaut

    Merci pour ces explications. Comme vous l'avez sans doute deviné je suis très très débutant dans ce type de programmation. Cela me permettra de mieux comprendre comment ca marche.

    Citation Envoyé par tourlourou Voir le message
    Quelles sont les options de création automatique des fiches ?
    où puis-je trouver ces paramètres?

    Citation Envoyé par Ph. B.
    Maintenant, j'aimerais bien voir le code du projet et comment sont appelées ces fiches...
    le code du projet est:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    program project1;
     
    {$mode objfpc}{$H+}
     
    uses
      {$IFDEF UNIX}{$IFDEF UseCThreads}
      cthreads,
      {$ENDIF}{$ENDIF}
      Interfaces, // this includes the LCL widgetset
      Forms, runtimetypeinfocontrols, Unit1, Unit2
      { you can add units after this };
     
    {$R *.res}
     
    begin
      Application.Initialize;
      Application.CreateForm(TForm2,Form2);
      Application.CreateForm(TForm1,Form1);
      Application.Run;
    end.

  5. #5
    Modérateur
    Avatar de tourlourou
    Homme Profil pro Yves Lemaire
    Biologiste ; Progr(amateur)
    Inscrit en
    mars 2005
    Messages
    2 221
    Détails du profil
    Informations personnelles :
    Nom : Homme Yves Lemaire
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : mars 2005
    Messages : 2 221
    Points : 4 914
    Points
    4 914

    Par défaut

    Code :
    1
    2
    3
    4
    5
    6
    begin
      Application.Initialize;
      Application.CreateForm(TForm2,Form2);
    // Application.CreateForm(TForm1,Form1); // commenter cette ligne annule la création automatique de la fiche
      Application.Run;
    end.
    On peut voir dans le menu projet->options les fiches en création automatique, en ajouter et en retirer ; le dpr (fichier projet) étant automatiquement adapté.
    Delphi 5 Pro et Code Typhon 4.41 sous Win 7 64 bits - Code Typhon 4.50 sous Ubuntu 14.04 64 bits et 12.04 64 bits (VM)

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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •