IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

[XE7] TLabeledEdit OnChange "spécial" ?


Sujet :

Composants VCL Delphi

  1. #1
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 520
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 520
    Points : 3 141
    Points
    3 141
    Par défaut [XE7] TLabeledEdit OnChange "spécial" ?
    Bonjour

    Dans une application, j'ai plusieurs fenêtres qui comporte de 1 à n TEdit servant de zone de saisie pour la recherche de ligne dans une une DBGrid (ou plus exactement dans le Dataset affiché dans le DBGrid).
    Jusque là, chaque saisie de recherche était codée dans les évènements OnChange de chaque TEdit. Le code consistait à :
    Désactiver les OnChange des TEdit non concernés, vider leur contenu, réactiver le OnChange et enfin prendre en compte la valeur saisie dans le TEdit en cours pour lancer une recherche sur une colonne dédiée.

    Sur une fenêtre pour commencer, j'ai remplacé les TEdit par des TLabeledEdit de façon à supprimer les TLabel associés qui étaient superflus.
    Ensuite, j'ai fais une procédure pour généraliser le traitement. En gros, ça donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    procedure TDatamod.Recherche(Table: TTable; NomIndex, NomChamp: string;
      ZonesS: array of TLabeledEdit);
    var
      I: Integer;
      Evt: TNotifyEvent;
    begin
      if (Length(ZonesS) = 0) or NomIndex.IsEmpty or NomChamp.IsEmpty then
        Exit;
     
      if Length(ZonesS) > 1 then
        for I := Succ(Low(ZonesS)) to High(ZonesS) do
        with TLabeledEdit(ZonesS[I]) do
        begin
          Evt := OnChange;     //  <----------  ici OnChange = nil  :-(
          OnChange := nil;
          Text     := '';
          OnChange := Evt;
        end;
     
      Recherche(Table, NomIndex, NomChamp, ZonesS[0].Text);
    end;
    C'est à dire que dans les OnChange, je passe en premier élément du tableau le TLabeledEdit "appelant" et les autres à la suite.

    Et là ça fait une plombe que je m'arrache les cheveux parce que dans le code, l'évènement OnChange est nil alors que c'est justement le OnChange qui a appelé la procédure de recherche.

    Je refais le même code mais cette fois avec des TEdit simples et là ça fonctionne parfaitement. Le OnChange est bien assigné.

    Le TLabeledEdit est un composant un peu spécial et j'imagine que ça vient de là.

    Auriez-vous une idée sur ce OnChange égal à nil dans un cas et pas dans l'autre ?

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 401
    Points : 653
    Points
    653
    Par défaut
    je n'ai pas testé mais à mon avis le problème vient de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Recherche(Table, NomIndex, NomChamp, ZonesS[0].Text);
    soit c'est une autre procédure que TDatamod.Recherche soit c'est elle et je ne comprend pas comment le code peut marcher

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 789
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 789
    Points : 25 777
    Points
    25 777
    Par défaut
    Recherche semble existé en overload, l'une en ZonesS: array of TLabeledEdit et l'autre en const S: string
    Personnellement, je pratique par une redéfinition locale de la classe pour éviter ce genre de manipulation à plusieurs endroits
    Là, dans un programme de configuration sur un serveur, je voulais mettre en évidence des champs modifiés par l'utilisateur, seuls ces champs seraient modifiés dans le fichier ini sous-jacent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    type
      TLabeledEdit = class(Vcl.ExtCtrls.TLabeledEdit)
      private
        FInitialText: string;
        procedure SetInitialText(const Value: string);
        function GetModified(): Boolean;
        procedure SetModified(Value: Boolean);
      protected
        procedure Change(); override;
      public
        property Modified: Boolean read GetModified write SetModified;
     
        property InitialText: string read FInitialText write SetInitialText;
     
      end;

    Et ton code se simplifie notablement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      if Length(ZonesS) > 1 then
        for I := Succ(Low(ZonesS)) to High(ZonesS) do
          TLabeledEdit(ZonesS[I]).InitialText := '';


    Pourquoi ne pas plutôt utiliser le Sender pour identifier l'objet ayant provoqué le OnChange initial ?
    Ce montage entre plusieurs TLabeledEdit me semble étrange et d'ailleurs pourquoi ne pas gérer un filtre multi-champ, si j'ai plusieurs champs de filtre, je m'attends qu'il soit exclusif par défaut, une case à cocher à proximité permettant de passer d'un exclusif à inclusif dans le filtre c'est un AND et un OR.

    Pour moi, la fonction Recherche doit être revue pour être mutli-colonne car cela manque d'ergonomie et de logique dans le cas contraire
    Si c'est sur une seule colonne, autant avoir un seul TLabeledEdit et un ComboBox pour choisir la colonne filtrée, c'est plus simple à comprendre.

    Voici l'implémentation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    { TLabeledEdit }
     
    procedure TLabeledEdit.Change();
    begin
      inherited Change();
     
      if Modified then
        EditLabel.Font.Style := EditLabel.Font.Style + [fsBold];
    end;
     
    function TLabeledEdit.GetModified(): Boolean;
    begin
      Result := inherited Modified;
    end;
     
    procedure TLabeledEdit.SetInitialText(const Value: string);
    begin
      FInitialText := Value;
      Text := Value;
      Modified := False;
    end;
     
    procedure TLabeledEdit.SetModified(Value: Boolean);
    begin
      inherited Modified := Value;
     
      if Value then
        EditLabel.Font.Style := EditLabel.Font.Style + [fsBold]
      else
        EditLabel.Font.Style := EditLabel.Font.Style - [fsBold];
    end;

  4. #4
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 520
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 520
    Points : 3 141
    Points
    3 141
    Par défaut
    Citation Envoyé par exoseven Voir le message
    je n'ai pas testé mais à mon avis le problème vient de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Recherche(Table, NomIndex, NomChamp, ZonesS[0].Text);
    soit c'est une autre procédure que TDatamod.Recherche soit c'est elle et je ne comprend pas comment le code peut marcher
    Cette procédure n'a rien à voir avec le problème. C'est un overload qui fait la recherche.
    Là, le problème, c'est que le OnChange est nil alors qu'il existe puisque c'est justement ce OnChange qui est déclenché pour appeler la fonction de recherche, précédée par la gestion des autres composants.

  5. #5
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 520
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 520
    Points : 3 141
    Points
    3 141
    Par défaut
    ça y'est, j'ai compris ...

    Je viens de refaire un exemple en dehors du programme concerné et ça fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    unit Unit5;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
     
    type
      TForm5 = class(TForm)
        LabeledEdit1: TLabeledEdit;
        LabeledEdit2: TLabeledEdit;
        LabeledEdit3: TLabeledEdit;
        LabeledEdit4: TLabeledEdit;
        procedure LabeledEdit1Change(Sender: TObject);
        procedure LabeledEdit2Change(Sender: TObject);
        procedure LabeledEdit3Change(Sender: TObject);
        procedure LabeledEdit4Change(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form5: TForm5;
     
    implementation
     
    {$R *.dfm}
     
     
    procedure Recherche(ZonesS: array of TLabeledEdit);
    var
      I: Integer;
      Evt: TNotifyEvent;
      Edt: TLabeledEdit;
    begin
      if (Length(ZonesS) = 0) then
        Exit;
     
      if Length(ZonesS) > 1 then
        for I := Succ(Low(ZonesS)) to High(ZonesS) do
        begin
          Edt := TLabeledEdit(ZonesS[I]);
          Evt := Edt.OnChange;
          Edt.OnChange := nil;
          Edt.Text     := '';
          Edt.OnChange := Evt;
        end;
    end;
     
    procedure TForm5.LabeledEdit1Change(Sender: TObject);
    begin
       Recherche([LabeledEdit1, LabeledEdit2, LabeledEdit3, LabeledEdit4]);
    end;
     
    procedure TForm5.LabeledEdit2Change(Sender: TObject);
    begin
       Recherche([LabeledEdit2, LabeledEdit1, LabeledEdit3, LabeledEdit4]);
    end;
     
    procedure TForm5.LabeledEdit3Change(Sender: TObject);
    begin
       Recherche([LabeledEdit3, LabeledEdit2, LabeledEdit1, LabeledEdit4]);
    end;
     
    procedure TForm5.LabeledEdit4Change(Sender: TObject);
    begin
       Recherche([LabeledEdit4, LabeledEdit2, LabeledEdit3, LabeledEdit1]);
    end;
     
    end.
    ça m'a permis de comprendre ce qu'il s'est passé.

    Les composants TLabeledEdit, je les ai obtenus en sélectionnant les TEdit présents et en utilisant ensuite le menu contextuel "Replace components ...".
    Dans mon exemple de test, j'ai utilisé directement les TLabeledEdit et ça fonctionne parfaitement.
    Cette possibilité "Replace components" semble avoir des lacunes.

    @ShaiLeTroll : En fait, utiliser le Sender pour changer la couleur, OK. Mais ça ne me donne pas les autres composants à "vider" de leur contenu.
    Après, je sais qu'on peut toujours faire mieux mais c'est toujours le même logiciel très mal codé que j'essaye petit à petit d'améliorer.
    Petite précision, ce logiciel est utilisé depuis longtemps par des personnes qui ont du mal à changer leurs habitudes de travail. Sinon, je mettrai une combo avec divers choix pour les colonnes possibles et ça irait bien mais ça risque de râler

    Dans la même idée que le TLabeledEdit, je vais essayer de faire un TLabeledDBEdit . Là aussi, ça permettrait de supprimer de trop nombreux TLabel mais aussi (t surtout) et pouvoir déplacer des TDBEdit plus facilement avec leurs étiquettes associées. Mais ça, c'est juste un projet

    Merci à tous les deux pour vos conseils

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

Discussions similaires

  1. Quote dans une requete...
    Par Isildur dans le forum Langage SQL
    Réponses: 6
    Dernier message: 20/06/2006, 11h57
  2. Problème de quote
    Par kennini dans le forum ASP
    Réponses: 4
    Dernier message: 20/11/2003, 10h40
  3. VARCHAR contenant une quote '
    Par tonyskn dans le forum Langage SQL
    Réponses: 2
    Dernier message: 29/05/2003, 20h21
  4. Quotes dans TFilenameEdit (RXLib)
    Par AnnSo dans le forum Composants VCL
    Réponses: 3
    Dernier message: 23/01/2003, 21h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo