Caricamento dati LabelledEdit

di il
9 risposte

Caricamento dati LabelledEdit

Ciao a tutti. Sono alle prime armi e mi trovo con il seguente problema: vorrei passare un valore da LabelledEdit1, oggetto visuale posizionato su Panel A, a una LabelledEdit creata insieme ad altre LabelledEdit in modo dinamico in Panel B.

Il mio piano è:
(1) individuare nel Panel B l'oggetto di destinazione tramite un ciclo cercando la LabelledEdit la cui Caption corrisponde a quella di LabelledEdit1
(2) passare il Text da LabelledEdit1 all'oggetto di destinazione

Eseguo il seguente codice come evento onChange di LabelledEdit1:

for i := 0 to PanelB.ControlCount - 1 do
(PanelB.Controls as TLabeledEdit).EditLabel.Caption = LabelledEdit1.EditLabel.Caption then
(PanelB.Controls as TLabeledEdit).Text = LabelledEdit1.Text;

Avrei tre domande:
1.) Il codice da errore "invalid class typecast" che sembra risultare dall'utilizzo di "(PanelB.Controls as TLabeledEdit)". Come si riesce ad evitare questo errore?
2a.) L'iterazione "for i := 0 to PanelB.ControlCount - 1 do" trova il doppio di oggetti confronto la quantità di TLabeledEdit presenti. Deduco che individua separatamente le Label e le Edit. C'è un modo di contare solo gli oggetti di un tipo?
2b) È possibile risalire con certezza dalla posizione di una Label alla posizione della corrispodente Edit? (ad es. n.2 TLabeledEdit itinerati come 4 oggetti in seguenza Label1, Label2, Edit1, Edit2; quindi: posizione Label1 + ControlCount/qtàTLabeledEdit = posizione di Edit1)

Mille grazie in anticipo per qualsiasi suggerimento. : )

Ale

9 Risposte

  • Re: Caricamento dati LabelledEdit

    Ad 1)
    risolto tramite conferma del tipo di oggetto:

    for i := 0 to PanelB.ControlCount - 1 do
    begin
    if (PanelB.Controls is TLabeledEdit) AND ((PanelB.Controls as TLabeledEdit).EditLabel.Caption = TLabeledEdit1.EditLabel.Caption) then
    (PanelB.Controls as TLabeledEdit).Text := TLabeledEdit1.Text;
    end;
  • Re: Caricamento dati LabelledEdit

    1) è fondamentale controllare sempre il tipo di un oggetto prima di fare un cast! Bene.
    2a) in effetti l'oggetto TLabeledEdit crea due controlli separati. Per contare devi fare un loop e contare quelli che ti "piacciono", non conosco altre strade.
    2b) la tua domanda non ha molto senso in quanto la property TLabeledEdit.EditLabel punta proprio alla "sua" TLabel!

    Ti segnalo la presenza, in tutti i discendenti di TComponent, della property Tag : integer, utilizzabile liberamente dall'utente. In casi come questo torna utile.
  • Re: Caricamento dati LabelledEdit

    Ciao Nicola,

    grazie per la tua risposta.
    Non sapendo questa mattina quale fosse la causa dell'errore, la domanda 2b puntava sull'eventualità di una gestione diversa da Label1 ed Edit1 appartenenti al medesimo oggetto TLabeledEdit1. Se invece, citando l'esempio sopra, la posizione 1 e 3 del ciclo prelevano lo stesso oggetto, allora va benissimo. : )

    Mi informo sulla property tag come da tuo consiglio.

    Ciao,
    Ale
  • Re: Caricamento dati LabelledEdit

    Mi si pone un'altra domanda, sempre riguardo allo stesso argomento.

    Come scritto sopra, il codice funziona perfettamente come evento onChange del TLabeledEdit mittente, oggetto visuale del Panel A, che invia (push) il contenuto ad un TLabeledEdit creato dinamicamente nel Panel B.

    Non funziona invece in direzione opposta (pull), ovvero richiedendo il contenuto nel momento della creazione del TLabeledEdit nel Panel B.

    Codice:

    for i := 0 to PanelA.ControlCount - 1 do
    begin
    if (PanelA.Controls is TLabeledEdit) AND ((PanelA.Controls as TLabeledEdit).Text <> EmptyStr) AND ((PanelA.Controls as TLabeledEdit).EditLabel.Caption = LabeledEdit.EditLabel.Caption) then
    LabeledEdit.Text := (PanelA.Controls as TLabeledEdit).Text;
    end;

    C'è un modo come fare funzionare il ciclo per il passaggio dei dati anche in pull?

    Senza utilizzare un ciclo, quindi abbinando uno a uno i campi ("if 1A = 1B then ... if 2A = 2B then...") mi funziona in pull.

    Ale
  • Re: Caricamento dati LabelledEdit

    al.delphi ha scritto:


    Mi si pone un'altra domanda, sempre riguardo allo stesso argomento.

    Come scritto sopra, il codice funziona perfettamente come evento onChange del TLabeledEdit mittente, oggetto visuale del Panel A, che invia (push) il contenuto ad un TLabeledEdit creato dinamicamente nel Panel B.

    Non funziona invece in direzione opposta (pull), ovvero richiedendo il contenuto nel momento della creazione del TLabeledEdit nel Panel B.
    for i := 0 to PanelA.ControlCount - 1 do
      begin
          if (PanelA.Controls[i] is TLabeledEdit) AND ((PanelA.Controls[i] as TLabeledEdit).Text <> EmptyStr) AND ((PanelA.Controls[i] as TLabeledEdit).EditLabel.Caption = LabeledEdit.EditLabel.Caption) then
          LabeledEdit.Text := (PanelA.Controls[i] as TLabeledEdit).Text;
      end;
    
    
    C'è un modo come fare funzionare il ciclo per il passaggio dei dati anche in pull?

    Senza utilizzare un ciclo, quindi abbinando uno a uno i campi ("if 1A = 1B then ... if 2A = 2B then...") mi funziona in pull.

    Ale
    Per favore usa (sempre) il tag CODE...

    Io lo avrei scritto così:
    
    Var
    	Lab : TLabeledEdit;
    ...
    
      for i := 0 to PanelA.ControlCount - 1 do begin
          if (PanelA.Controls[i] is TLabeledEdit) then begin
            Lab := PanelA.Controls[i] as TLabeledEdit; //Questo rende MOLTO più leggibile il codice e non peggiora certo le prestazioni
            if (Lab.Text <> EmptyStr) AND (Lab.EditLabel.Caption = LabeledEdit.EditLabel.Caption) then
               LabeledEdit.Text := Lab.Text;
             Break; //essendo 1:1 una volta trovata la prima non ho bisogno di continuare il ciclo
          end; //if  
      end; //for
    
    Sembra giusto ma nel codice manca la parte precedente e quella successiva: non sappiamo cosa fai! Posta il contenuto completo della procedura.
  • Re: Caricamento dati LabelledEdit

    Personalmente (nel mio piccolo) non ho capito niente, stai cercando castare mele con pere (e a volte fichi)
    hai scritto:

    al.delphi ha scritto:


    if (PanelA.Controls is TLabeledEdit) AND ((PanelA.Controls as TLabeledEdit).Text <> EmptyStr) AND ((PanelA.Controls as TLabeledEdit).EditLabel.Caption = LabeledEdit.EditLabel.Caption) then
    a parte i nomi dei componenti che confondono, stai castando una lista ad un oggetto cercando nella lista l'oggetto, molte idee ma molto ben confuse, cmq se usi una versione di delphi "aggiornata" ti consiglio l'uso della unit RTTI, invece in caso contrario allora un bel ripasso alla VCL non sarebbe male.
    cmq
    Il componente ( oggetto, classe chiamalo come vuoi) TPanel contiene dei controlli, e questi controlli sono elencati dalla property "controlcount" dunque, per semplificare, hai un array (che parte da 0) di TControl dentro il componente TPanel con un loop for vai a scandire tutti i TControl poi per ogniuno devi fare i debiti cast, il tuo codice dovrebbe diventare qualcosa del tipo (semplificato):
    
    for i := 0 to PanelA.ControlCount - 1 do  // per tutti i controlli presenti nel panel
    begin
      if (PanelA.Controls[i] is TLabeldeEdit) then  // ok beccato TLabeledEdit 
       begin
          if (PanelA.Controls[i] as TLabeledEdit).Text <> EmptyStr) AND  
             ((PanelA.Controls[i] as TLabeledEdit).EditLabel.Caption = <nome e property del componente da confrontare>.Caption) then
            <nome e property del componente da settare>.Text := (PanelA.Controls[i] as TLabeledEdit).Text;
       end;     
    end;
    
    Ma, ancora non riesco a capire cosa cerchi di ottenere...

    W.
  • Re: Caricamento dati LabelledEdit

    Wolfen ha scritto:


    cmq se usi una versione di delphi "aggiornata" ti consiglio l'uso della unit RTTI, invece in caso contrario allora un bel ripasso alla VCL non sarebbe male.
    Non capisco perché dai un così pessimo consiglio! È evidente che @al.delphi è un utente alle prime armi e la VCL non la deve ripassare ma sta cominciando a vederla per la prima volta! RTTI è una cosa complessa ed utile a programmatori esperti e si usa abbastanza raramente.

    Il componente ( oggetto, classe chiamalo come vuoi) TPanel contiene dei controlli, e questi controlli sono elencati dalla property "controlcount"
    Col cavolo! ControlCount è il numero di oggetti discententi della classe TControl ed accessibili con Panel.Controls[n]. Parallelamente ci sono anche i discendenti di TComponent, in numero ComponentCount ed accessibili con Panel.Components[n]. Ma questo lo sapeva già.
    È importante notare che
    1) i discendenti di TControl sono controlli visuali, di solito quelli che metti nel form e che interagiscono con l'utente
    2) poiché TControl discende da TComponent troverai che TUTTI i TControls[] sono ANCHE in Components[].
    Quindi l'uso di Controls[] per cercare un oggetto è, nel caso in questione, corretto.
    Ma, ancora non riesco a capire cosa cerchi di ottenere...
    Forse sta cercando di imparare...
  • Re: Caricamento dati LabelledEdit

    nicolap ha scritto:


    Non capisco perché dai un così pessimo consiglio! È evidente che @al.delphi è un utente alle prime armi e la VCL non la deve ripassare ma sta cominciando a vederla per la prima volta! RTTI è una cosa complessa ed utile a programmatori esperti e si usa abbastanza raramente.
    Io non la penso in questo modo, e se devo settare property o cercare componenti "in giro" il primo passo che faccio è sempre la strada RTTI, chiamiamoli "gusti personali".
    2) poiché TControl discende da TComponent troverai che TUTTI i TControls[] sono ANCHE in Components[].
    Quindi l'uso di Controls[] per cercare un oggetto è, nel caso in questione, corretto.
    ... forse in parole un po' diverse (forse più criptiche) ma credo di aver detto la stessa cosa

    Wolfen ha scritto:


    Il componente ( oggetto, classe chiamalo come vuoi) TPanel contiene dei controlli, e questi controlli sono elencati dalla property "controlcount"....

    nicolap ha scritto:


    Quindi l'uso di Controls[] per cercare un oggetto è, nel caso in questione, corretto.
    Non mi sembra di aver mai messo in dubbio questa affermazione l'unica cosa che ho sottolineato è stato il cast di una lista con un oggetto

    nicolap ha scritto:


    Forse sta cercando di imparare...
    Visto le figure che ci sono in questo forum credo che, se chiede, gli sarà dato tutto il supporto di cui ha bisogno, di questo non ho il minimo dubbio
  • Re: Caricamento dati LabelledEdit

    Scusate, non volevo creare disagi. Più avanti mi studierò anche le Run Time Type Information.

    @nicola
    Grazie per il suggerimento di utilizzare il Break. Inserendolo nella seconda condizione, i campi vengono caricati correttamente nei campi di destinazione.
    [CODE] Var Lab : TLabeledEdit; ... for i := 0 to PanelA.ControlCount - 1 do begin if (PanelA.Controls[i] is TLabeledEdit) then begin Lab := PanelA.Controls[i] as TLabeledEdit; if (Lab.Text <> EmptyStr) AND (Lab.EditLabel.Caption = LabeledEdit.EditLabel.Caption) then begin LabeledEdit.Text := Lab.Text; Break; end; end; end; Perfetto! : )

    Ale
Devi accedere o registrarti per scrivere nel forum
9 risposte