ChildForm Indépendantes

Résolu
kizermomo Messages postés 6 Date d'inscription vendredi 27 octobre 2006 Statut Membre Dernière intervention 26 juillet 2007 - 24 juil. 2007 à 10:41
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 - 25 juil. 2007 à 10:47
Bonjour a tous,  en espérant être assez clair et précis sur ma demande.

Voici mon problème:
je crée un application qui utilise une MDIForm et plusieurs MDIChildForm.

Mon appli doit créer plusieures fenêtres enfants identiques
(qui contiennent des TChart qui dessinent un graphique, un timer et autres).Jusque là pas
de problème.

Par contre à l'exécution, je peut ouvrir autant de fenêtres que je
le souhaite mais elles sont "reliées" (c'est le même graphique qui
apparait ans chaque fenêtre).

Mes questions:
Faut-il crée une fonction constructor particulière pour ma FormChild concernée?

Comment créer des fenêtre qui sont indépendantes les unes des autres?
J'ai l'impression qu'à l'heure actuelle certains des composants de ma form enfant ne ne sont pas crées séparémment.
Voici ma procédure pour créer ma Form enfant:
procedure TListForm.CreateMdiChild(const Name : string);

var
   Child: TChargeForm;
begin
   Child := TChargeForm.Create(Application);
   Child.Caption := Name;
end;

Et voila mon contructeur de From

constructor TChargeForm.Create(AOwner : TComponent);
begin
   inherited Create(AOwner);
end;

Quelqu'un pourrait eclairé ma lanterne?? Malgrè des recherches je n'ai pas trouvé (ou mal cherché) de solution semblable au problème soulévé!! Merci d'avance!!

Kizermomo

8 réponses

cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
25 juil. 2007 à 10:47
re,

les MDI n'ont rien de très spécial. Ce sont des forms normal. Et ce sont des objects. Si tu comprend bien ces deux points, t'as les grandes lignes. Après les trucs spécial MDI, ça vient directement de windows.

--------

var
  ChargeForm: TChargeForm; //inutile. efface cette ligne. (c'est utile pour les form qui sont instancié une seul fois. comme ça t'as déjà l'instance)

--------

c'est juste, il te faut des var LOCAL ou des champs. SInon, TOUS les enfants vont partager la même var et donc tu aurra des problème de "concurence" cad d'écriture "simultanée" depuis plusieurs forms.

tu peux aussi les déclarer en var local de ta procedure GetList.

------
ChartCharge.Series[I].Repaint; //generalement inutile. ev. remplace par un "chart.invalidate" à la fin de ta mise a jour.
-------
Series : array[0..40] of TLineSeries;
si tu utilise UNE var local (voir mon precedent post), tu peux te passer de ce tableau.
-------   

bon code,

PS: renseigne toi sur: TObjectList; series.beginupdate ; setlenght (as-tu réelement besoin de 65000 valeurs?);

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
3
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
24 juil. 2007 à 12:12
salut,

ta méthode est correct. (On pourrait l'amélioré et plein d'autre méthode exist avec quelques avantage que tu n'as pas (comme utiliser une function plustot qu'une procedure pour créer tes mdiChild)). Mais c'est juste.

ton problème vient surement de la manière dont tu crée ton TChart/series.

Pourrais-tu nous indiquer comment sont crée les chart/series? On design time(ie: Delphi)? Run time(ie: par code)?
Utilises-tu des var global dans ta form MdiChild? (tu ne devrait utiliser que des champs de l'object form)

bon code,

Loda

PS: c'est marrant, ça fait une année que je boss sur un prog MDI avec des TChart. :-D
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
kizermomo Messages postés 6 Date d'inscription vendredi 27 octobre 2006 Statut Membre Dernière intervention 26 juillet 2007
24 juil. 2007 à 12:27
Salut Loda,

merci de t'interesser à mon problème.
Ma Form enfant contient un TChart  qui est déclaré comme suit:
type
  TChargeForm = class(TForm)
    PnlActn: TPanel;
    GrdPnlActn: TJvGradient;
    MemReq: TMemo;
    BtnLaunch: TJvXPButton;
    EdInt: TSpinEdit;
    Label1: TLabel;
    ChartCharge: TChart;
    Timer: TTimer;

Ensuite, pour initialiser mon Chart et les Séries, je le fais lors de la création de ma Form comme ceci:
procedure TChargeForm.FormCreate(Sender: TObject);
var
   I : integer;
begin
   If ListForm.ChbxMultiSel.Checked then begin
      If ListForm.DBGridList.SelectedRows.Count>0 then begin
         With ListForm.DBGridList.DataSource.DataSet do begin
            For I:=0 to ListForm.DBGridList.SelCount-1 do begin
               GotoBookMark(pointer(ListForm.DBGridList.SelectedRows.Items[I]));
               Series[I] := TLineSeries.Create(Self);
               Series[I].ParentChart := ChartCharge;
               Series[I].Title := FieldByName('Lib').AsString;            
               TUrl[I] := MainForm.TblEtude.FieldByName('Url').AsString;
               ChartCharge.Series[I].SeriesColor := MainForm.TblEtude.FieldByName('Clr').AsVariant;
            end;//for
         end;//with
      end;//if
   end//if
   ListForm.Close;
end;
Pour Info ma variable Series est un array de TLineSeries (car nombre de courbe variable) déclarée après implementation.
Le tableau TUrl contient une adresse qui me permet d'aller faire une requête.
Mon appli doit dessiner un graphique en fonction du temps de réponse pour chaque requête effectuée.

Kizermomo

Suis-je assez clair?? Parfois j'en doute
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
24 juil. 2007 à 13:51
re,

"Pour Info ma variable Series est un array de TLineSeries (car nombre de courbe variable) déclarée après implementation."
c'est ça. Comme il est déclarer dans l'unité au lieu de la class, c'est une var GLOBAL. donc tu la partage entre toute tes forms.

essai un truc genre (pas testé):

procedure TChargeForm.FormCreate(Sender: TObject);
var
   I : integer;
  aSeries: TLineSeries;
begin
   If ListForm.ChbxMultiSel.Checked then begin
      If ListForm.DBGridList.SelectedRows.Count>0 then begin
         With ListForm.DBGridList.DataSource.DataSet do begin
            For I:= 0 to ListForm.DBGridList.SelCount-1 do begin
               GotoBookMark(pointer(ListForm.DBGridList.SelectedRows.Items[I]));
              
               aSeries := TLineSeries.Create(Self);
               aSeries.ParentChart : = ChartCharge; // add la serie au chart ; tu peux aussi faire ChartCharge.AddSeries(ASeries). c'est la meme choses
               aSeries.Title := FieldByName('Lib').AsString;           
               TUrl[I] := MainForm.TblEtude.FieldByName('Url').AsString;
               aSeries.SeriesColor := MainForm.TblE

<hr size="2" width="100%" />
renseigne toi sur la portée/visibilité des variable/champs. Ev. fait quelques test dans une form simple.

un champs d'object est une part de l'object (et donc unique par object). Une espace mémoire est alloué pour chaque champs de chaque object.

une var dans une unité (après ou avant implementation avec le mot VAR) est global (public ou privé). et donc n'existe qu'UNE fois.

fait aussi bien la différence entre "self" et "form1". self refer l'object (instance). alors que Form1 est UN (parmis d'autre) object de type Tform1. dans les methode de class, utilise toujours self (et non la var global form1)

bon code,

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
kizermomo Messages postés 6 Date d'inscription vendredi 27 octobre 2006 Statut Membre Dernière intervention 26 juillet 2007
24 juil. 2007 à 17:31
J'ai testé avec la modification mais rien n'y fait.
Par contre j'ai aussi un TTimer, un TDataSource et un composant fait maison qui me permet de faire ma requête.
Faut'il que je crée ces composants spécifiquement lors de la création de mes fiches enfants???

Kizermomo
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
25 juil. 2007 à 09:19
re,

c'est vrai que la modif que je t'ai indiqué n'explique pas ton problème de "lien".

dit moi, comment remplit tu les séries? Utilise tu des var global pour fournir les données? Il y a forcement un moment ou tu reutilise un pointeur ou une var global pour chaque form. Et ton timer? c'est pour un refresh? stp copie le code pour voir.
utilises-tu "DBGridList.SelectedRows" dans tes calculs? ou une autre partie de ton DBGridList?

peux-tu me précisier ce qui est la même choses entre tes form? les données du chart (je suppose)? Arrive tu a voir quel données sont affichée? Les première? les dernières? la selection de la grille?

"Faut'il que je crée ces composants spécifiquement lors de la création de mes fiches enfants???"
tout ce qui doit être unique par enfant doit être crée dans le formcreate ou le create. Note que la pluspart des create sont appelé automatiquement. Si ce n'est pas clair ce qui doit être crée où, dit moi.
Le ttimer par exemple: Si tu le "pose" sur la fiche(comme pour un boutton), tu n'as pas besoin de le crée à la main.

pour le timer, si c'est pour faire un refresh tu peux en avoir qu'un pour toute les form, mais il faut qu'il appel une methode "Monrefresh" pour chaque form.

A+

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
kizermomo Messages postés 6 Date d'inscription vendredi 27 octobre 2006 Statut Membre Dernière intervention 26 juillet 2007
25 juil. 2007 à 09:52
Tout d'abord, encore merci pour tes précisions. J'apprécie qu'on prenne le temps de m'explique. Je n'aime pas utiliser des méthodes sans les comprendre et comme les MDI sont nouvelles pour moi je voudrait "maitriser" le sujet.

Voila ce que je déclare dans mon type TForm:
type
  TChargeForm = class(TForm)
    PnlActn: TPanel;
    GrdPnlActn: TJvGradient;
    MemReq: TMemo;
    BtnLaunch: TJvXPButton;
    EdInt: TSpinEdit;
    Label1: TLabel;
    ChartCharge: TChart;
    Timer: TTimer;
    TableOffre: TXMLCDS; //composant maison
    DtSrc: TDataSource;
    TableOffreI0: TIntegerField;
    TableOffreS1: TStringField;
    TableOffreS2: TStringField;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnLaunchClick(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;
    procedure GetList;
  end;
var
  ChargeForm: TChargeForm;
implementation

uses UnitList, UnitMain;
var
   Col : integer =0;
   K : integer = 0;
   MyVal : array[0..65000,0..40] of integer; // tableau on je stocke les valeurs des séries à insérer dans mon graphique
   TTime : array[0..65000] of string;  //tableau dans lequel je stocke l'heure ou les requêtes sont effectuées
   TUrl : array[0..40] of string; 
   TClr : array[0..40] of TColor;
// le problème vient-il du fait que je déclare mes variables ici
{$R *.dfm}

Pour ce qui est de mon Timer, il me sert à gérer l'interval où les requêtes ont lieu (donc pas le même sur chaque fiche enfant).
Je fais un refresh de mon Chart à la fin de ma requête une fois que j'ai insérer ma valeur dans le tableau  et mis la série concernée à jour (plusieures séries quand plusieures courbes):
//procédure pour click sur bouton de lancement des requêtes
procedure TChargeForm.BtnLaunchClick(Sender: TObject);
begin
   Timer.Interval := (EdInt.Value*1000);
   EdInt.Enabled := False;
   FillChar(MyVal,SizeOf(MyVal),0);
   FillChar(TTime,SizeOf(TTime),0);
   Col := 0;
   ChartCharge.MaxPointsPerPage := Trunc(21600/EdInt.Value);
   Timer.Enabled := True;
end;

//procédure lors de l'activation du timer
procedure TChargeForm.TimerTimer(Sender: TObject);
begin
   GetList;
end;

Pour mettre a jour mes séries, je le fait dand a procédure GetList:
procedure TChargeForm.GetList;
var
   Result : boolean;
   I,J : integer;
   T1,T2,T3 : real;
   D : TDateTime;
begin
   T1 := Time;
   D := Date;
   For I:=0 to ChartCharge.SeriesCount-1 do begin
      With TableOffre do begin
         If Active then Close;
         T2 := Time;
         Url := TUrl[I];
      end;//with //avec mon with, j'envoi ma requête
      T3 := Time;
      MyVal[Col,I] := MilliSecondsBetween(T2,T3); //je calcul le temp mis pour effectuer ma requete
      ChartCharge.Series[I].Clear;
      If Col>ChartCharge.MaxPointsPerPage then
         K:=K+1;
      For J:=K to Col do
         ChartCharge.Series[I].Add(MyVal[J,I],TTime[J],TClr[I]); //Je met ma série à jour
      If MyVal[Col,I]>ChartCharge.LeftAxis.Maximum then
         ChartCharge.LeftAxis.Maximum := MyVal[Col,I];
      ChartCharge.Series[I].Repaint;
   end;//for
   MemReq.Lines.Add(DateTostr(Date)+' '+TimeToStr(T1)+': Requêtes effectuées');
   TTime[Col]:= TimeToStr(T1);
   Col := Col+1;
end;

Autrement voici aussi le code de ma procédure Create de la form (où je crée les séries nécessaires):

procedure TChargeForm.FormCreate(Sender: TObject);
var
   I : integer;
   Series : array[0..40] of TLineSeries;
begin
   Col := 0;
   If ListForm.ChbxMultiSel.Checked then begin
      If ListForm.DBGridList.SelectedRows.Count>0 then begin
         With ListForm.DBGridList.DataSource.DataSet do begin
            For I:=0 to ListForm.DBGridList.SelCount-1 do begin
               GotoBookMark(pointer(ListForm.DBGridList.SelectedRows.Items[I]));
               Series[I] := TLineSeries.Create(Self);
               Series[I].ParentChart := ChartCharge;
               Series[I].Title := FieldByName('Lib').AsString;
               TClr[I] := MainForm.TblEtude.FieldByName('Clr').AsVariant;
               TUrl[I] := MainForm.TblEtude.FieldByName('Url').AsString;
               ChartCharge.Series[I].SeriesColor := TClr[I];
            end;//for
         end;//with
      end;//if
   end//if
end;
A la lecture de ta réponse précedente, je pense que mes variable tableau et autres ne sont surement pas déclarées au bon endroit.
Est-ce bien ca ou je n'en ai pas fini avec ce souci!?!

Kizermomo
0
kizermomo Messages postés 6 Date d'inscription vendredi 27 octobre 2006 Statut Membre Dernière intervention 26 juillet 2007
25 juil. 2007 à 10:06
C bon, problème résolu a priori, j'ai juste changé la déclaration de mes variables coome suit:

type
  TChargeForm = class(TForm)
    PnlActn: TPanel;
    GrdPnlActn: TJvGradient;
    MemReq: TMemo;
    BtnLaunch: TJvXPButton;
    EdInt: TSpinEdit;
    Label1: TLabel;
    ChartCharge: TChart;
    Timer: TTimer;
    TableOffre: TXMLCDS;
    DtSrc: TDataSource;
    TableOffreI0: TIntegerField;
    TableOffreS1: TStringField;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnLaunchClick(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
  private
    { Private declarations }
   Col : integer;
   K : integer;
   MyVal : array[0..65000,0..40] of integer;
   TTime : array[0..65000] of string;
   TUrl : array[0..40] of string;
   TClr : array[0..40] of TColor;
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;
    procedure GetList;
  end;
Il semblerait que ce soit ok, je confirme dès que j'ai mieux testé tout ca.

Kizermomo
0
Rejoignez-nous