Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    Pulsante deve agire su Caption di Gbox in Tframe come?

    ciao a tutti....

    sono disperato perchè non riesco a sbloccare una situazione.

    un pulsante deve generare n numeri casuali e riditrubuirli tra le caption di n groupbox contenute in n tframe... solo che non riesco a fare nulla di tutto ciò...

    MainForm
    -->pulsante Crea Frame (btnNuovoFrame)
    -->pulsante Genera Numeri (Button1)
    -->pannello contenitore del frame (pannello)

    TFrmGriglia è il frame di cui sopra
    gbox è la groupbox da modificare

    una variabile publica (ngriglie) inizializzata a 0 OnFormCreate (MainForm) tiene conto di quanti frame il pulsante Crea genera.

    codice:
    procedure TMainForm.btnNuovoFrameClick(Sender: TObject);
    begin
      ngriglie:=ngriglie+1;
      with TFrmGriglia.Create(pannello) do
        begin
          parent:=pannello;
          left:=sn;       {gestione posizionamento}
          top:=115;       //idem
          Inc(sn,115);    // "
          name:='frmGriglia'+IntToStr(i);  //creazione di nome univoco
          Inc(i);
          gbox.Caption:='Mia Capation';    //caption standard e statica
          Inc(let);
          cont:=cont+1;
          end;
    end;
    questa procedura genera ad ogni click un frame che al suo interno presenta la groupBox gbox.

    io vorrei che un altro pulsante generasse una serie di valori numerici casuali e li inserisse all'interno delle gbox.Caption.

    tralasciando la gestione del vettore che memorizza i dati casuali da 1 a ngriglie, vorrei sapere come si fa ad alterare il testo delle caption da codice, tenendo conto che i frame non son presenti su form, ma vengono generati a runtime dall'utente.

    avevo provato così (gazie ad alka)
    codice:
      for i := 0 to pannello.ComponentCount - 1 do
      begin
        if (pannello.Components[i] is TGroupBox) then
          TGroupBox(pannello.Components[i]).Caption := Ncasuale[i];
      end;
    ma così non succede nulla

    idee o miracoli?

    grazie e

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296

    Re: Pulsante deve agire su Caption di Gbox in Tframe come?

    Originariamente inviato da Lyll0
    ma così non succede nulla
    Non succede nulla per forza...hai usato il codice che ti ho scritto senza applicarlo al caso in esame.

    Devi sapere che tra i componenti esiste un legame detto ownership. Quando crei il tuo Frame, passi come parametro al metodo Create la variabile pannello...perchè fai questo?

    Il metodo Create dei componenti (si intendono componenti anche i controlli visuali) accettano come parametro un secondo componente che viene considerato Owner. L'Owner di un componente provvede a distruggere il componente stesso quando esso viene distrutto.

    Quando posizioni pulsanti dalla Palette ad una form, ad esempio, la form diviene l'Owner di tali pulsanti e si accolla la responsabilità di distruggere tali pulsanti nel momento stesso in cui la form viene distrutta. Questo consente di evitare al programmatore la scrittura di un'istruzione per la deallocazione della memoria usata dai componenti, una per ognuno.

    Le proprietà ComponentCount e Components, riferite ad un componente, restituiscono rispettivamente il numero di componenti posseduti e l'istanza dei singoli componenti dato l'indice che va da 0 a (ComponentCount - 1).

    Questa è l'essenza del concetto di "ownership", da distinguere bene dal concetto di "parentship", cioè del legame esistente tra un controllo (non un componente, ma specificatamente un controllo) e un altro controllo, detto Parent, che lo contiene.

    Il codice che ti ho suggerito non funziona poichè ciascun frame viene creato avendo come owner il pannello; se il codice non ottiene effetto, vuol dire che non si arriva mai ad individuare una delle GroupBox: bastava soffermarsi con un breakpoint ed eseguire il ciclo volta per volta per verificarlo; infatti, è probabile che la proprietà ComponentCount restituisca il numero di frame, che sono gli unici componenti posseduti dal pannello, poichè i componenti GroupBox sono posseduti dal frame e pertanto sono accessibili dalla proprietà Components dei singoli frame, non del pannello.

    La relazione è:
    Pannello contenitore --possiede--> Frame[0..n]
    Frame[i] --possiede--> GroupBox (e altri)

    Detto questo, potendo anche semplificare, è possibile modificare il codice come segue:
    codice:
    for i := 0 to pannello.ComponentCount - 1 do
    begin
      if (pannello.Components[i] is TFrmGriglia) then
       TFrmGriglia(pannello.Components[i]).gbox.Caption := Ncasuale[i];
    end;
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    intanto ti ringrazio per la spiegazione esaustiva.
    l'errore che ho fatto deriva dal fatto che non ho mai usato il costrutto
    [i]TFrmGriglia(pannello.Components).gbox.Caption
    e dunque non so cosa sto facendo.

    ricevo cmq questo errore quando provo a premere sul pulsante:

    ---------------------------
    Debugger Exception Notification
    ---------------------------
    Project ProgettoGestoreSessione.exe raised exception class EAccessViolation with message 'Access violation at address 00404A1C in module 'ProgettoGestoreSessione.exe'. Read of address 00000009'. Process stopped. Use Step or Run to continue.
    ---------------------------
    OK Help
    ---------------------------


    e non cambia nulla.

    PS: Read of Address genera ogni volta un vaolre diverso:
    FFFFFFFF9
    FFFFFFFFC
    ...

  4. #4
    aspetta ci sono quasi.

    l'errore me lo da, sembrerebbe a causa del vettore Ncasuale[i] e forse a cusa dell'operazione IntToStr(NCasuale[i])

  5. #5
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    intanto ti ringrazio per la spiegazione esaustiva.
    l'errore che ho fatto deriva dal fatto che non ho mai usato il costrutto
    [i]TFrmGriglia(pannello.Components).gbox.Caption
    e dunque non so cosa sto facendo.
    Come fai a non sapere cosa stai facendo? Ti ho appena spiegato a cosa serve il codice e perchè si usa così. Ci riprovo.

    Allora, i componenti che si trovano sul frame (la GroupBox e tutti gli altri eventuali controlli che hai inserito) sono "posseduti" dal frame. Il frame è l'owner di questi controlli ed è possibile scandirli usando ComponentCount e Components in combinazione.

    Per intenderci, scrivendo qualcosa del tipo
    codice:
    ...FrmGriglia1.Components[1].Name...
    intendiamo accedere alla proprietà Name del secondo componente che si trova sul frame FrmGriglia1.

    Questo è per spiegare il significato della scrittura, che potrà esserci utile per accedere eventualmente ai componenti inseriti all'interno di un frame, avendo però un riferimento al frame stesso.

    Il codice che ti ho scritto scandisce i Components del pannello, che sono i frame TFrmGriglia.

    Nel codice che ti ho scritto, eseguo un ciclo da 0 al numero di componenti - 1 posseduti dal pannello, tra i quali devono esserci anche i frame. Attraverso l'operatore is, verifico se il componente i (da 0 a n - 1) è un TFrmGriglia. In caso affermativo, eseguo un cosiddetto "casting", cioè forzo il trattamento di quel componente come se fosse un TFrmGriglia (e non ci sono rischi, poichè ho già controllato preventivamente che fosse appartenente a quel tipo con is); trattando il componente come TFrmGriglia, riesco ad accedere a tutti gli elementi (proprietà, componenti, ecc.) che sono pubblici, cioè visibili dall'esterno, tra cui la GroupBox di nome "gbox", di cui vado ad impostare la Caption...tutto qui.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  6. #6
    fatto!!!!!!!!!!!!!

    era come avevo previsto: l'errore era causato dalla coversione ad intero:

    VECCHIO CODICE ERRATO:
    codice:
    procedure TMainForm.Button1Click(Sender: TObject);
    var i:integer;
        dado:VettoreDiInteri;
    begin
      for i:=0 to ngriglie do
        dado[i]:=RandomRange(1,20));
      for i := 0 to pnlPuntiFerita.ComponentCount - 1 do
        begin
          if (pnlPuntiFerita.Components[i] is TFrmGriglia) then
            TFrmGriglia(pnlPuntiFerita.Components[i]).GroupBox2.Caption :=IntToStr(dado[i]);  <--!!!!!!
        end;
    end;
    CODICE FUNZIONANTE
    codice:
    procedure TMainForm.Button1Click(Sender: TObject);
    var i:integer;
        dado:VettoreStringhe;
    begin
      for i:=0 to ngriglie do
        dado[i]:=IntToStr(RandomRange(1,20));
      for i := 0 to pnlPuntiFerita.ComponentCount - 1 do
        begin
          if (pnlPuntiFerita.Components[i] is TFrmGriglia) then
            TFrmGriglia(pnlPuntiFerita.Components[i]).GroupBox2.Caption :=dado[i]; <--!!!!!
        end;
    end;
    cmq vedi che se ti ci metti riesci ad aiutarmi....

    forse ho capito perchè in passato non sei riuscito a capirmi:
    perchè non mettevo il codice in rete!

    grazie e vedi di risolvermi il problema del setfocus, nullafacente
    (SCHERZO, NON TI ARRABBIARE!)

  7. #7
    Originariamente inviato da alka
    Come fai a non sapere cosa stai facendo? Ti ho appena spiegato a cosa serve il codice e perchè si usa così. Ci riprovo.

    Allora, i componenti che si trovano sul frame (la GroupBox e tutti gli altri eventuali controlli che hai inserito) sono "posseduti" dal frame. Il frame è l'owner di questi controlli ed è possibile scandirli usando ComponentCount e Components in combinazione.

    Per intenderci, scrivendo qualcosa del tipo
    codice:
    ...FrmGriglia1.Components[1].Name...
    intendiamo accedere alla proprietà Name del secondo componente che si trova sul frame FrmGriglia1.

    Questo è per spiegare il significato della scrittura, che potrà esserci utile per accedere eventualmente ai componenti inseriti all'interno di un frame, avendo però un riferimento al frame stesso.

    Il codice che ti ho scritto scandisce i Components del pannello, che sono i frame TFrmGriglia.

    Nel codice che ti ho scritto, eseguo un ciclo da 0 al numero di componenti - 1 posseduti dal pannello, tra i quali devono esserci anche i frame. Attraverso l'operatore is, verifico se il componente i (da 0 a n - 1) è un TFrmGriglia. In caso affermativo, eseguo un cosiddetto "casting", cioè forzo il trattamento di quel componente come se fosse un TFrmGriglia (e non ci sono rischi, poichè ho già controllato preventivamente che fosse appartenente a quel tipo con is); trattando il componente come TFrmGriglia, riesco ad accedere a tutti gli elementi (proprietà, componenti, ecc.) che sono pubblici, cioè visibili dall'esterno, tra cui la GroupBox di nome "gbox", di cui vado ad impostare la Caption...tutto qui.
    si hai ragione, rileggendo il tuo codice mi ero reso conto.

    è sorto un problema scemo:
    ogni volta che premo il pulsante siccome la caption in realtà deve contenere anche del testo prima tipo:
    'FRAME 1 | Ncasuale'
    avevo scritto così:
    codice:
    TFrmGriglia(pnlPuntiFerita.Components[i]).GroupBox2.Caption :=TFrmGriglia(pnlPuntiFerita.Components[i]).GroupBox2.Caption+' :: '+dado[i] //IntToStr(dado[i]);
    solo che ogni volta che premo il pulsante mi si aggiungono i numeri casuali dietro!!!!
    'FRAME 1 | Ncasuale1 | NCasuale2 | NCasualeEtc...'
    dov'è e quand'è che devo pulire la caption per visualizzare un solo numero? (porca miseria)

    scusami per l'insistenza. :tongue:

  8. #8
    ho risolto con il mitico metodo della manipolazione delle stringhe!

    codice:
    caption:=TFrmGriglia(pnlPuntiFerita.Components[i]).GroupBox2.Caption;
    Delete(caption, Pos(':: ',Caption)-1, Length(Caption));
    TFrmGriglia(pnlPuntiFerita.Componentsi]).GroupBox2.Caption :=Caption+' :: '+dado[i] //IntToStr(dado[i]);
    ciao e grazie e scusa!

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Mio Diooooo, che soluzione è??

    Cancella quel cattivo esempio di malaprogrammazione.

    Se devi visualizzare un testo del tipo Casella n.ro 1, lasci la Caption come vuoi, memorizzi la parte di testo in una costante
    codice:
    const
      SPrefissoGroupBoxCaption = 'Casella n.ro ';
    e poi la imposti come Caption sul controllo accodandole il numero:
    codice:
    GroupBox1.Caption := SPrefissoGroupBoxCaption + IntToStr(numero);
    P.S.: una piccola richiesta per le povere anime che ti aiutano: se hai un problema, non scrivere subito sul forum per rifletterci esattamente il secondo dopo e scrivere, dopo un minuto, che hai trovato la soluzione mentre qualcun altro stava già scrivendo da 10 minuti il proprio messaggio, magari ben curato in modo che fosse il più comprensibile, da scartare poi perchè hai già trovato la soluzione.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    già bella idea quella della costante me la ricorderò per il futuro.

    ma il nome della casella era

    Casella (costante)
    +
    Lettera (incrementale gestita in un'altra parte del programma)
    +
    Numero Casuale (generato alla fine del programma)

    non potevo accorpare le due cose perchè vanno distinte e non possono viaggiare insieme.
    fidati con tre righe di codice ne sono uscito pure troppo bene.

    PS: hai ragione riguardo al discorso messaggi impulsivi.
    lo faccio pure quando qualcosa sembra funzionare ed invece poi non funziona.
    solo che nel primo caso ci rimetto poco io e 10 minuti tu*, nel secondo invece, chi mi aiutava neppure si rifà vivo perchè mi prende per un coglione!

    *in realtà 10 minuti sprecati per uno che neppure si conesce è brutto per quersto ti chiedo umilmente SCUSA!

    ciao e grazie

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.