Précédent   Forum du club des développeurs et IT Pro > Autres langages > Pascal > Lazarus
Lazarus Forum d'entraide sur Lazarus, l'EDI RAD multiplateforme basé sur Free Pascal
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 01/11/2012, 00h16   #1
spetit24
Invité de passage
 
Inscription : octobre 2012
Messages : 2
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : octobre 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.
spetit24 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2012, 09h18   #2
tourlourou
Modérateur
 
Homme Yves Lemaire
Biologiste ; Progr(amateur)
Inscription : mars 2005
Messages : 1 680
Détails du profil
Informations personnelles :
Nom : Homme Yves Lemaire
Âge : 50
Localisation : France, Yvelines (Île de France)

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

Informations forums :
Inscription : mars 2005
Messages : 1 680
Points : 3 090
Points : 3 090
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 2.80 sous Win 7 64 bits - Code Typhon 2.70 / Ubuntu 12.04 64 bits
tourlourou est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/11/2012, 14h42   #3
Ph. B.
Expert Confirmé
 
Avatar de Ph. B.
 
Homme Philippe
Inscription : avril 2002
Messages : 1 026
Détails du profil
Informations personnelles :
Nom : Homme Philippe
Âge : 46
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : avril 2002
Messages : 1 026
Points : 2 651
Points : 2 651
Envoyer un message via ICQ à Ph. B. Envoyer un message via Skype™ à Ph. B.
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.
Ph. B. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/11/2012, 07h34   #4
spetit24
Invité de passage
 
Inscription : octobre 2012
Messages : 2
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : octobre 2012
Messages : 2
Points : 1
Points : 1
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.
spetit24 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/11/2012, 09h22   #5
tourlourou
Modérateur
 
Homme Yves Lemaire
Biologiste ; Progr(amateur)
Inscription : mars 2005
Messages : 1 680
Détails du profil
Informations personnelles :
Nom : Homme Yves Lemaire
Âge : 50
Localisation : France, Yvelines (Île de France)

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

Informations forums :
Inscription : mars 2005
Messages : 1 680
Points : 3 090
Points : 3 090
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 2.80 sous Win 7 64 bits - Code Typhon 2.70 / Ubuntu 12.04 64 bits
tourlourou est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 03h04.


 
 
 
 
Partenaires

Hébergement Web