TobjectList avec objets différents : récupération [Résolu]

Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
- - Dernière réponse :  Utilisateur anonyme - 15 oct. 2011 à 17:07
Bonjour le forum,

Je me pose une question sur TObjectList.

Voici un exemple de code :
procedure TForm1.Button1Click(Sender: TObject);
var
  listeobjet: TObjectList;

begin
  try
    listeobjet := TObjectList.Create(False);
    listeobjet.Add(Label1);
    listeobjet.Add(Edit1);
    if (listeobjet.Items[0] is TLabel) then
      TLabel(listeobjet.Items[0]).Font.Size := 20;

    if (listeobjet.Items[1] is TEdit) then
      TLabel(listeobjet.Items[1]).Font.Size := 20;
  finally
    FreeAndNil(listeobjet);
  end;
end;


Je précise pour ceux qui ne manipulent pas cette classe qu'il faut ajouter Contnrs dans les uses !

Sur l'exemple précédent on peut imaginer faire une boucle for pour parcourir tous les éléments de la liste d'objets et mettre des cas pour gérer tous les contrôles avec des "is" mais je trouve que cela fais créer beaucoup de code !

J'ai remarqué qu'avec ClassName il était possible de récupérer TLabel, etc. sous forme textuelle.

Connaîtriez-vous un moyen de se passer du is du style :
listeobjet.Items[0].ClassName(listeobjet.Items[0]).Font.Size := 20;

Merci d'avance pour vos pistes !

Que la force soit avec vous !
Afficher la suite 

Votre réponse

18 réponses

Meilleure réponse
3
Merci
Effectivement la propriété TFont est protégée dans la classe TControl. Ceci dit il est tjs possible d'appeler une propriété protégée

Voilà le bout de code que tu cherches (J'ai testé c'est bon)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,Contnrs;

type
 TCustomControl=class(TControl);

  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Memo1: TMemo;
    Button1: TButton;
    CheckBox1: TCheckBox;
    ScrollBar1: TScrollBar;
    procedure Button1Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  listeobjet: TObjectList;
  Index:Integer;
begin
  try
    listeobjet := TObjectList.Create(False);
    listeobjet.Add(Label1);
    listeobjet.Add(Edit1);
    For Index:=0 To ListeObjet.Count-1 Do
    TCustomControl(listeobjet.Items[index]).Font.Style := [fsBold];
  finally
    FreeAndNil(listeobjet);
  end;
end;
end.


Pour la seconde technique proposée, j'ai pas cherché (Vu que cela me semble inutile).

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 96 internautes nous ont dit merci ce mois-ci

Commenter la réponse de Utilisateur anonyme
Messages postés
308
Date d'inscription
jeudi 29 septembre 2005
Dernière intervention
17 septembre 2013
0
Merci
Moien,

hope it helps :

ici.

Luc.
Commenter la réponse de beckerich
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
0
Merci
Beckerich,

Merci pour ton aide !

Je suis tombé sur le même lien lors de mes recherches sur google avant de rédiger ce message mais il ne s'applique pas dans mon cas car il suppose l'utilisation de TForm uniquement et dans mon cas je ne connais pas à l'avance lors du parcours de la liste d'objet la classe sur laquelle je suis. En effet, ce peut-être TEdit, TLabel, TCheckbox, TDBCheckbox, etc.

Pour le moment j'ai contourné le problème en mettant autant de cas avec is que d'objet utilisé. Voici un extrait du code utile :
    for i := 0 to Pred(listeobjet.Count) do
    begin
      if (listeobjet.Items[i] is TLabel) then
        ;// TLabel(listeobjet.Items[i]).Faire quelquechose

      if (listeobjet.Items[i] is TEdit) then
        ;// TEdit(listeobjet.Items[i]).Faire quelquechose

      // Ainsi de suite pour les autres
    end;


En tous cas merci pour ton aide !

Si tu as une autre piste, ou si quelqu'un d'autre en a une, n'hésitez pas

Que la force soit avec vous !
Commenter la réponse de informatixo
0
Merci
Salut,

Présenté comme cela la réponse est non :) : En fait il faudrait savoir ce que tu cherches vraiment à faire. Tu ne veux modifier que la propriété Font d'un oject (enfin si elle existe) ? Si oui il y a moyens de faire autrement avec un Try Except mais je suis pas sur que niveau perf ca soit génial.

A toi de nous en dire plus :)
Commenter la réponse de Utilisateur anonyme
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
0
Merci
Bonjour le forum,

Merci Francky de me venir en aide !

Effectivement je constate que je n'ai pas été assez précis et qu'il est difficile de m'aider alors reprenons.

J'ai différents contrôles posés sur une fiche et je veux principalement modifier la propriété Font de certains d'entre eux pour les mettre en évidence.
Toutes les contrôles que je veux modifier ont bien une propriété Font. Comme le traitement est assez similaire je me suis dis que le plus simple était de mettre les objets à modifier dans une liste d'objets et de la parcourir en appliquant les modifications.

Vous allez me dire que je me prend la tête à vouloir le faire de cette façon alors que je pourrais le faire à la conception mais en fait il me faut modifier le font ou le remettre à son état initial sous certaines conditions ! De ce fait avec ma liste j'ai les objets que je dois manipuler à tout moment. Cela me semble être le moyen le plus rapide.

Pour le moment afin de ne pas être bloqué j'ai fais comme je disais dans le message précédent à savoir avec des is pour chaque contrôle.

Une dernière précision, je connais les différents contrôle que je place dans la liste d'objets puisque c'est moi qui les rentrent en dur dans la liste à la création de la fiche mais à chaque itération je ne sais pas précisément lequel ça va être ! Voilà pourquoi je cherche un moyen de connaître dynamiquement la classe de l'objet pour le transtyper correctement lors de sa récupération de la liste d'où le is.

Merci à tous pour votre aide.

Que la force soit avec vous !
Commenter la réponse de informatixo
0
Merci
Je te mets sur la voix de la solution à laquelle je pense : Est ce que ces composants n'ont pas un ancentre commun admettant la propriété Font ? Si oui le tour est joué : un try except en utilisant la propriété as et c'est gagné
Commenter la réponse de Utilisateur anonyme
0
Merci
Arffff sinon une solution à la foxi : Un ptit

In [TEdit,TLabel,TBlabla]


Ca peut le faire aussi . A toi de tester.

Désolé je n'ai pas delphi sur ce poste pour te filer un bout de code tester (Ca devra attendre lundi)
Commenter la réponse de Utilisateur anonyme
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
0
Merci
Salut,

Ta liste d'objet existe déjà. C'est Self.Components[].
Ensuite, il ne te reste qu'à jouer sur leur Tag pour les identifier.

Un exemple avec TButton et TEdit :
A la conception, tu mets le Tag des Edits concernés à 1 et le Tag des Boutons concernés à 2.
Highlight(1) Allumera (=> en gras) ces Edits
Highlight(2) Allumera ces Boutons
Et pareil pour les éteindre avec SwitchOff().

procedure TForm1.Highlight(TagNb: Integer);
var i : Integer;
begin
  for i := 0 to Self.ComponentCount -1 do begin
    if Self.Components[i].Tag = TagNb then begin
      Case TagNb of
        1: (Self.Components[i] as TEdit).  Font.Style := [fsBold];
        2: (Self.Components[i] as TButton).Font.Style := [fsBold];
      end;
    end;
  end;
end;

procedure TForm1.SwitchOff(TagNb: Integer);
var i : Integer;
begin
  for i := 0 to Self.ComponentCount -1 do begin
    if Self.Components[i].Tag = TagNb then begin
      Case TagNb of
        1: (Self.Components[i] as TEdit).  Font.Style := [];
        2: (Self.Components[i] as TButton).Font.Style := [];
      end;
    end;
  end;
end;

Je te laisse adapter ça à tes besoins précis en jouant sur la valeur des Tag...

Que la force soit avec toi !
Commenter la réponse de Caribensila
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
0
Merci
Bonsoir le forum,

Merci à vous tous du coup de main.

@caribensila : merci beaucoup grâce à toi je viens d'apprendre le coup du "as" ! Si j'ai bien compris, TEdit(Self.Components[i]) équivaut à (Self.Components[i] as TEdit) ? Concernant mon problème précis ta solution me semble plus complexe à utiliser telle quelle. Cependant je vais essayer de m'en inspirer pour améliorer mon code alors un grand merci.

@Francky : merci à toi aussi pour ton axe de réflexion. J'ai essayé de mettre en oeuvre le code qui utilise ta piste mais je suis bloqué. Alors je t'explique pourquoi car ton idée me plaît bien aussi. Comme j'utilise des contrôles dont l'ancêtre est TWinControl et d'autres dont l'ancêtre est TGraphicControl, le plus ancien ancêtre commun est TControl. Donc j'ai essayé ceci :

TControl(listeobjet.Items[i]).Font.Style := [fsBold];


Mais j'obtiens le message d'erreur suivant : "E2362 Impossible d'accéder au symbole protected TControl.Font" ce qui me semble être normal puisque cette classe a été conçue pour être dérivée.

Peut-être ai-je mal compris la solution vers laquelle tu voulais m'amener ?

En attendant vos commentaires, encore un grand merci à vous deux !

Que la force soit avec vous !
Commenter la réponse de informatixo
0
Merci
Pour répondre à ta question


@caribensila : merci beaucoup grâce à toi je viens d'apprendre le coup du "as" ! Si j'ai bien compris, TEdit(Self.Components[i]) équivaut à (Self.Components[i] as TEdit) ? Concernant mon problème précis ta solution me semble plus complexe à utiliser telle quelle. Cependant je vais essayer de m'en inspirer pour améliorer mon code alors un grand merci.


Je te copie l'aide de Delphi : Elle répond clairement à ta question


L'opérateur as effectue des transtypages avec vérification. L'expression :

objet as classe

renvoie une référence au même objet que objet mais avec le type spécifié par classe. A l'exécution, objet doit être une instance de la classe désignée par classe ou de l'un de ses descendants ou avoir la valeur nil ; sinon une exception est déclenchée. Si le type déclaré objet n'a pas de lien avec classe (c'est-à-dire si les types sont distincts ou si l'un n'est pas l'ancêtre de l'autre), il y a erreur de compilation. Par exemple :

with Sender as TButton do

begin
Caption := '&Ok';
OnClick := OkClick;
end;

Les règles de priorité des opérateurs obligent souvent à placer entre parenthèses un transtypage as. Par exemple :

(Sender as TButton).Caption := '&Ok';
Commenter la réponse de Utilisateur anonyme
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
0
Merci
Bonsoir le forum,

Merci beaucoup Francky pour tes explications précieuses ! Vu que tu as eu la gentillesse de me donner la réponse je me suis attardé longuement sur le code que tu m'as donné pour bien le comprendre.

Tu m'arrêteras si je me trompe mais si j'ai bien compris, pour utiliser une propriété protégée d'une classe, il suffit de créer une nouvelle classe dérivée de la classe qui contient la propriété protégée et de transtyper la propriété désirée avec la classe dérivée.

Grâce à toi je viens d'apprendre quelquechose de vraiment nouveau qui résout mon problème donc je t'en remercie et je considère ton avant dernière réponse comme réponse accepté.

Merci à tous de m'avoir aidé à résoudre mon problème.

Que la force soit avec vous !
Commenter la réponse de informatixo
0
Merci
Tu m'arrêteras si je me trompe mais si j'ai bien compris, pour utiliser une propriété protégée d'une classe, il suffit de créer une nouvelle classe dérivée de la classe qui contient la propriété protégée et de transtyper la propriété désirée avec la classe dérivée.


Tu as tout à fait compris. Beaucoup de gens passent à coté de ce genre de petite chose et pourtant des fois ca rend bien des services.
Un peu comme les Is-As-In, les set et autre petits trucs qui permettent de faire des codes beaucoup plus propres et beaucoup moins longs.
Après il y a des questions d'optimisations qui sont à prendre en compte aussi, mais il est important de sortir des sentiers battus (Par exemple toujours utiliser des If Then ou des Case Of) et de voir d'autres manières de faire. Delphi est un langage riche de part ses fonctionnalités et beaucoup d'entre nous parfois (Moi y compris) oublient cette réalité. Si je peux te donner un conseil : Regarde beaucoup les codes et interventions de f0xi sur le forum (C'est grace à lui que j'ai appris qu'il faut parfois sortir des sentiers battus ).

En tout cas ravis d'avoir pu t'aider.

Ps : Tu peux aussi prendre en compte la remarque de Cari qui est vraie et aussi importante en terme d'intérets.
Commenter la réponse de Utilisateur anonyme
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
0
Merci
Puisque je passe par ici, un autre (très) petit truc pour écrire du 'joli' code :

au lieu de faire :
for i := 0 to Pred(listeobjet.Count) do...

ou :
for i := 0 to listeobjet.Count-1 do...

faire :
for i := 0 to high(listeobjet) do...


@Francky
« il est important de sortir des sentiers battus (Par exemple toujours utiliser des If Then ou des Case Of) »


Je ne vois pas ce dont tu parles...
Mais comme t'as l'air de bonne humeur (pour une fois ), tu vas nous donner un exemple ou un lien, hein?
Commenter la réponse de Caribensila
0
Merci
Un exemple pourrave (J'ai pas trop envie de chercher )

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  Decimal = 0..10;
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

Function IsOdd(Const Nb : Decimal) : Boolean;
Begin
  Result:=True;

  {Methode 1 : Newbie}
//  If (Nb=0) Or (Nb=2) Or (Nb=4) Or (Nb=6) Or (Nb=8) Or (Nb=10) Then Result:=False;

  {Methode 2 : Cari}
  Case Nb Of
    0,2,4,6,8,10 : Result:=False;
  End;

  {Methode 3 : f0xi}
  If Nb In [0,2,4,6,8,10] Then Result:=False;
End;



procedure TForm1.Button1Click(Sender: TObject);
begin
 If IsOdd(4) Then Showmessage('Impaire') Else Showmessage('Paire');
end;

end.
Commenter la réponse de Utilisateur anonyme
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
0
Merci
Ah, ok !
Je vois...

Merci.
Commenter la réponse de Caribensila
Messages postés
133
Date d'inscription
mercredi 4 février 2004
Dernière intervention
25 juillet 2012
0
Merci
Bonsoir à tous,

Désolé pour la réactivité mais hier impossible d'accéder au site.
Toujours dans le même esprit, n'aurions nous pas pu écrire une seule ligne comme suit dans la fonction IsOd ?

Result := (Nb mod 2) <> 0;


A plus,

Que la force soit avec vous !
Commenter la réponse de informatixo
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
0
Merci
Tout à fait.
Mais quand Francky fait dans le pourrave, c'est du pourrave !

De toute façon, y'a une fonction Delphi pour ça.
Fonction dont d'ailleurs j'adore l'exemple que donne l'Aide de D7 :

begin
if Odd(5)then
Canvas.TextOut(10,10,'5 est impair.')
else
Canvas.TextOut(10,10,'Il y a un problème quelque part!');
end;
Commenter la réponse de Caribensila
0
Merci
C'était juste un exemple (pourrave j'avais prévenu ) : J'avoue il était mal choisi mais c'était juste pour illustrer

Oui Cari la fonction Odd existe : Du reste le premier a en avoir parlé sur le site, c'est notre cher Delphiprog suite à un message de GrandVizir si mes souvenirs sont bons
Commenter la réponse de Utilisateur anonyme

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.