QuickReport4 + FindComponent = EAccessViolation [Résolu]

Signaler
Messages postés
129
Date d'inscription
mercredi 4 février 2004
Statut
Membre
Dernière intervention
25 juillet 2012
-
Messages postés
129
Date d'inscription
mercredi 4 février 2004
Statut
Membre
Dernière intervention
25 juillet 2012
-
Bonsoir le forum,

Je fais encore appel à votre bienveillance pour un problème d'accès à des composants.

Pour résumer je cherche à créer dynamiquement un report et à pouvoir accéder aux labels qu'il contient pour les modifier en fonction des besoins du programme.

J'ai une première fiche ("frmMenuPrincipal") qui contient un simple bouton me permettant de lancer le rapport et qui contient le code suivant sur l'évènement "Clic" :

procedure TfrmMenuPrincipal.btnLancerRapportClick(Sender: TObject);
var
  qrlabel: TQRLabel;

begin
  qrlabel := TQRLabel.Create(self);
  qrlabel.Name := 'qrlabel1';
  qrlabel.Parent := frmRapport.qrPage;

  qrlabel := TQRLabel.Create(self);
  qrlabel.Caption := 'Label 2';
  qrlabel.Name := 'qrlabel2';
  qrlabel.Left := 600;
  qrlabel.Parent := frmRapport.qrPage;

  frmRapport.qrPage.Preview;
end;

J'ai ensuite une seconde form ("frmRapport") qui contient un objet "TQuickRep" (qui s'appelle "qrPage" dans mon exemple) avec une bande de détail.

Deux labels sont créés dynamiquement sur le "qrPage" depuis le code du bouton ci-dessus.

Je voudrais pouvoir modifier les labels qui ont été créé dynamiquement grâce à un évènement du "qrPage", c'est la raison pour laquelle je n'ai pas mis de "Caption" pour le "qrlabel1" dans le code du bouton.

Comme je ne savais pas trop comment procéder, j'ai utilisé l'évènement "OnStartPage" comme en témoigne le code ci-dessous :

procedure TfrmRapport.qrPageStartPage(Sender: TCustomQuickRep);
begin
  TQRLabel(FindComponent('qrlabel1')).Caption := 'Label 1';
end;

Le problème c'est que la ligne de code ci-dessus me génère une exception de type "EAccessViolation".

Je me doute que ce n'est pas la faute de l'ordinateur mais bien du développeur que je suis mais je ne vois pas d'où proviens mon erreur.

Mon hypothèse est que du fait que j'ai réalisé un "Preview" depuis le bouton, je ne peux pas accéder à mon objet "qrlabel1" et donc il me dis que j'essaye d'accéder à un objet inexistant ?

Ais-je raison ?

Si oui, comment puis-je procéder pour aboutir à la solution que je désire ?

Je tiens à préciser que ceci est un exemple simplifié d'une application industrielle que je reprends afin de rendre des rapports dynamiques car des champs doivent ou ne doivent pas être affichés en fonction des résultats d'un automate stockés dans une base de données.

J'ai déjà une grande quantité de code qui se situe dans l'évènement "OnStartPage" et qui servait jusque là à remplir le contenu des labels fixes que je suis en train de rendre dynamique.

Une première solution bien contraignante serait de placer le code qui gère le contenu des labels dynamiques dans le code du bouton mais je ne sais pas trop si celà serait vraiment judicieux.

Alors avant de m'embarquer dans mes délires solitaires, je préfère demander l'avis de la communauté delphienne.

Je vous remercie d'avance de l'attention que vous porterez à ce post et des réponses que vous pourriez me fournir.

Cordialement,
informatixo

Que la force soit avec vous !

5 réponses

Messages postés
129
Date d'inscription
mercredi 4 février 2004
Statut
Membre
Dernière intervention
25 juillet 2012
1
Après avoir relu ta réponse plusieurs fois Shai, je me suis aperçu que j'avais effectivement mal compris la différence entre la notion de "owner" et celle de "Parent".

Et effectivement celà ne pouvait engendrer qu'une erreur de violation d'accès.

Je suis donc finalement arrivé à trouver la solution qui me convenait le mieux et que voici :

Je crée mes composants sur la page du Quickreport (qrPage) en m'inspirant du premier exemple que tu m'a donné de cette façon TQRlabel.Create(frmRapport.qrPage).

Ensuite j'y accède depuis le "OnStartPage" en faisant frmRapport.qrPage.FindComponent('qrlabel1')).Caption := 'Label 1'

Mon problème résidait dans le fait que je ne précisait pas au "FindComponent" où cherchait les composants.

Le fait de créer les composants sur la page du QuickReport me permet de générer plusieurs rapports de manière dynamique tout en gardant les mêmes noms de composants sur chaque page de rapport puisque le propriétaire n'est plus la form mais bien successivement chaque page de rapport.

Ainsi mon problème est enfin résolu.

Je te remercie encore Shai pour ta participation qui m'a permis de comprendre quelquechose d'essentiel dans la gestion dynamique des composants.

Que la force soit avec vous !
Messages postés
50
Date d'inscription
mardi 8 octobre 2002
Statut
Membre
Dernière intervention
21 décembre 2011

qrlabel := TQRLabel.Create(frmRapport);


le Composant passé en paramètre du Create est le Owner, et c'est lui qui contient la liste des components qui est parcouru via FindComponent

Le EAccessViolation est que FindComponent renvoie nil

<hr />
Shai Le Troll
!! Aide via F1 !! Pensez-y !! 
Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le conf
Messages postés
129
Date d'inscription
mercredi 4 février 2004
Statut
Membre
Dernière intervention
25 juillet 2012
1
Tout d'abord merci beaucoup de ta réponse Shai.

J'ai effectivement essayé ta solution mais celà ne fonctionne pas car le composant n'est pas situé sur le QuickReport (il s'agit d'un TQRLabel et non d'un TLabel).

J'ai donc essayé une variante de ta solution qui est "TQRLabel.Create(frmRapport.qrPage)" mais celà ne fonctionne pas non plus !

J'avais fais un qrlabel.Parent := frmRapport.qrPage n'est-ce pas la même chose que la ligne ci-dessus ?

En attendant merci beaucoup de ta participation.

Cordialement,
informatixo

Que la force soit avec vous !
Messages postés
50
Date d'inscription
mardi 8 octobre 2002
Statut
Membre
Dernière intervention
21 décembre 2011

Je ne comprend pas  ta réponse,

"car le composant n'est pas situé sur le QuickReport (il s'agit d'un TQRLabel et non d'un TLabel)."

il y a pas de relation de parent (ancrage / visibilité) mais de possession d'objet ... et ta phrase n'a ni queue ni tête

Que renvoie le FindComponent ? nil ? ou autre chose, tu cast en TQRLabel mais sans vérifier la classes ...

Si tu as des problèmes, tu peux ajouter dans une TStringList triées ...

ObjectsNamedList.AddObject( 'qrlabel1', qrlabel);

et dans le OnStartPage

idx := ObjectsNamedList.IndexOf('qrlabel1');
if idx >= 0 then
begin
  QRLabel := (ObjectsNamedList.Objects[i] as TQRLabel);
  if Assigned(QRLabel) then
    QRLabel := 'Label 1';
end;

Sinon, ayant fait de l'industrie, QuickReport selon mes tests, ne supporte pas d'être lancé en Thread, si tu dois faire des impressions, il faut les pooler dans une liste puis les imprimer séquentiellement dans un Timer, mais tu n'en es pas encore là ...




<hr />
Shai Le Troll
!! Aide via F1 !! Pensez-y !! 
Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le conf
Messages postés
129
Date d'inscription
mercredi 4 février 2004
Statut
Membre
Dernière intervention
25 juillet 2012
1
Effectivement ma phrase n'a ni queue ni tête et je m'en excuse (pourtant j'ai relu avant de poster mais visiblement pas assez).

Je voulais dire "car le composant est situé sur le QuickReport (il s'agit d'un TQRLabel et non d'un TLabel)."".

Pour ta seconde question le FindComponent renvoi effectivement "nil".

Si je crée mon label sur le "frmRapport" lorsque que j'exécute il n'apparaît pas sur mon report. En revanche si je met comme parent "qrPage" (c'est-à-dire mon TQuickRep) alors là il apparaît bien.

Mais le problème c'est toujours mon FindComponent dans le "OnStartPage" qui passe pas et me génère une "EAccessViolation" car il est "nil".

Cordialement,
informatixo

Que la force soit avec vous !