Gambas-it

Archivi (sola lettura) => Programmazione (Gambas 2) => Topic aperto da: dex - 11 Ottobre 2009, 01:13:49

Titolo: [RISOLTO]form child
Inserito da: dex - 11 Ottobre 2009, 01:13:49
salve raga

ho creato un form main, e ora sto creando altri form che si dovrebbero comportare come child, quando riduco ad icona il main anche tutti i child devono seguirlo.

mi date una mano?
Titolo: Re: form child
Inserito da: md9327 - 12 Ottobre 2009, 11:57:47
Un'ipotesi è quella di salvare nella form generale tutti i collegamenti alle form figlie, nel senso che basta che crei un oggetto array (Object[]) a cui aggiungi mano mano le altre form. Questo oggetto potrebbe essere una proprietà della form stessa.
Nell'evento iconize della form padre, ti fai un loop dell'array, ed esegui la stessa cosa per tutti gli oggetti contenuti in esso.
Idem con patate per altri eventi o funzionalità che vuoi inserire.
E' ovvio che devi gestire anche la chiusura di una form figlia, ovvero comunicare alla master che lei stà morendo, e di attivare tutte le procedure del caso, compreso un'eventuale divieto di chiusura, utile nel caso tu voglia completare delle validazioni.
Titolo: Re: form child
Inserito da: dex - 15 Ottobre 2009, 13:11:29
in teoria riesco a capire il tuo consiglio, ma quando vado per metterlo in pratica mi incarto.

mi faresti un esempio solo della prima parte, e cioè creare un array e inserire una form figlia?
Titolo: Re: form child
Inserito da: md9327 - 15 Ottobre 2009, 15:02:10
Nella classe Form master, devi dichiare e aggiungere una proprietà alla stessa classe:
Codice: [Seleziona]

PRIVATE $forms AS NEW Object[]

L'istruzione deve essere interna al file di classe, ma esterna da qualsiasi metodo o funzione. In teoria devi collocarla ad inizio file classe.
Quindi dichiari un tuo metodo:
Codice: [Seleziona]

PUBLIC SUB ChildClosing(child AS Object)
  DIM n AS Integer
  FOR n = 0 TO $forms.Max
    IF ($forms[n] = child) THEN
      $forms.Remove(n)
      BREAK
    END IF
  NEXT
END

il metodo sarà poi utilizzato dalle form figlie per comunicare alla master la loro chiusura.

Quando apri una nuova Form figlia, ad esempio tramite un pulsante ad-hoc, basta che nel metodo Click() del pulsante, aggiungi queste istruzioni:
Codice: [Seleziona]

PUBLIC SUB Button_Click()
  DIM newForm AS NEW Form()
  $forms.Add(newForm)
  newForm.Show()
END

Ovviamente io ho usato un oggetto Form generico, che può essere sostituito da una tua Form, l'importante è che l'aggiungi all'array $forms.
Nelle Form figlie, dovresti implementare alcune istruzioni, sia nel metodo _new() che nella Close() di ciascuna, in modo da definire nella figlia chi sia il padre, e notificare alla master la chiusura della sua figlia:
Codice: [Seleziona]

PRIVATE $master AS Object

PUBLIC _new(master AS Object)
  $master = master
END

PUBLIC Form_Close()
  $master.ChildClosing(ME)    
END

Come vedi, nelle figlie è necessario utilizzare il costruttore nascosto di ogni oggetto, o classe, gestito da Gambas: _new().
Questo per poter definire un nuovo parametro "master", con cui gli viene passato il riferimento alla Form master, e che viene salvato nella proprietà $master della form. La proprietà $master sarà poi utilizzata per chiamare un metodo della form master, appunto ChildClosing(), con cui notificare della sua chiusura la form master.

A parte i giri di parole, che spero siano state chiare, tu puoi far interagire le varie Form in modo anche più complesso; ad esempio potresti impedire la chiusura delle form figlie, bloccando l'evento tramite il metodo ChildClosing(), oppure creare un link di comunicazione tra le finestre a prescidere dalla gerarchia padre/figlia, e via dicendo...

Spero sia stato tutto chiaro, in caso contrario, fammi sapere.

Bye
Titolo: Re: form child
Inserito da: dex - 15 Ottobre 2009, 18:18:14
md sei grande
se riusciro a coronare il mio sogno ( formattare windows )  lo dovro anche a te.

grazie
Titolo: Re: form child
Inserito da: Ceskho - 15 Ottobre 2009, 18:28:15
Citazione

desadex ha scritto:
md sei grande
se riusciro a coronare il mio sogno ( formattare windows )  lo dovro anche a te.

grazie


Beh si.....ha la sua età....ma non denigrarlo solo perchè è anziano...poverino...
Titolo: Re: form child
Inserito da: md9327 - 15 Ottobre 2009, 21:17:38
Roba da matti... ma chi ha lasciato la porta aperta??!!??

Sento uno spiffero...    :freddo:

...
...

 :-P  :-P  :-P  :hammer:  :hammer:  :hammer:  :shit:  :shit:  :shit:  :duro:  :duro:  :giullare:  :giullare:  :giullare:  :ble:  :ble:  :ble:  :ot:  :spam:
Titolo: Re: form child
Inserito da: dex - 20 Ottobre 2009, 19:51:38
anni di visualbasic mi hanno rovinato, o forse perchè non ho mai usato array, ma non riesco ad uscirne.

md ho due form il primo cassa ed il secondo griglia.

mi aiuti a capire come inserirli nell'array?
Titolo: Re: form child
Inserito da: md9327 - 21 Ottobre 2009, 11:53:53
Forse se spieghi meglio cosa vuoi ottenere, forse riesco a darti una mano.

Se hai compreso la mia precedente spiegazione, non credo sia complicato applicarla a quello che vuoi fare.

Ad ogni modo, descrivi cosa vuoi fare...
Titolo: Re: form child
Inserito da: dex - 21 Ottobre 2009, 22:56:03
ho un form main che si apre a pieno schermo, all'interno apro a misure prestabilite vari form, per ora ne ho 2 , il primo cassa ed il secondo griglia. a progetto ultimato ne dovrebbero essere più di 70.

ma per ora concentriamoci sui due form.

per la chiusura del main si deve chiudere tutto il progetto e mi è bastato mettere quit nel main e funziona.

il problema è che se invece di chiudere il main lo riduco a icona i form cassa e griglia che si trovano aperti restano li.
vorrei che anche loro seguissero il main togliendosi dal desk o meglio ancora farli scomparire con hide (attenzione non voglio chiuderli in quanto perderei i dati), alla riapertura del main dovrebbero tornare al loro posto o con massimize oppure con show.
Titolo: Re: form child
Inserito da: md9327 - 22 Ottobre 2009, 11:44:38
Allora... due cosine...

Mi sembra di aver rispoto ad un'altra discussione, circa l'utilizzo della classe Workspace; dovresti dargli un'occhiata...

Ad ogni modo, gradirei sapere se la tua applicazione si basa su una Form specifica, o sull'oggetto Application.

Questa cosa è molto importante, in quanto un programma può essere controllato in maniera più efficiente e professionale, se il tutto si basa sulla classe Application.

Nelle librerie di Gambas, esiste una classe, Application, che è statica, ovvero utilizzabile direttamente senza l'uso di creazioni varie. Le librerie Gambas per gtk e kde, hanno incorporata una versione derivata da questa, con alcune proprietà e metodi aggiuntivi.
A parte questo, la classe Application contiene un riferimento alla MainView, ovvero la Form principale dell'applicazione.
Da questa MainView, che può essere una classica Form, possono essere create ulteriori finestre, come è ovvio, e queste si adeguano automaticamente allo stato della MainView.
Un esempio reale è l'ambiente ide di Gambas che, partendo da un Application, crea la sua MainView (la finestra madre, nella sua interezza), che contiene a sua volta le finestre che apre (da menu o da codice).

Spero di spiegarmi al meglio...

Questa logica viene chiamata MDI (multiple document interface).

Se, nel tuo caso, il tuo programma si appoggia su una classica Form (logica SDI, single document interface), e vuoi che le figlie seguano il suo stato, la cosa diventa complicata, in quanto all'applicazione non è stata definita un vista principale. La complicazione consiste nell'implementare una sorta di collegamento comunicativo tra le varie finestre, che viene gestito in particolare da una form specifica. Questo comporta l'aggiunta di un mucchio di codice, e la logica deve controllare bene i protocolli usati nella comunicazione.

Tutto il discorso può essere ovviato dall'uso della logica che ti ho descritto prima, ovverro Application + MainView. Tieni conto che tutto il giochetto viene gestito in maniera trasparente dall'applicazione stessa, per cui ti evita di impiccarti con la scrittura di codice astruso e complicato, oltre che poco manutenibile.

La logica SDI viene usata, di norma, in piccole applicazioni con una singola form, che contiene tutte le caratteristiche del tuo programma. Se il programma prevede di gestire molte più cose, credo sia più logico usare il metodo MDI.

Se non ricordo male, l'uso del sistema SDI era molto di moda con VB, ma solo per le piccole applicazioni. Di solito, in progetti grandi, l'avere finestre svolazzanti e indipendenti, in giro per lo schermo, era cosa molto poco gradita, oltre che faceva perdere il controllo, anche di chi usava il programma.
Titolo: Re: form child
Inserito da: dex - 24 Ottobre 2009, 20:12:39
la storia è questa:
Ho realizzato un programma di gestione con visualbasic che si basa sul principio dell'mdi in quanto fra form, griglie e report ci sono oltre 300 maschere.

ora dopo l'ennesimo problema dei virus con quel sacco di pulci di xp, e dato che, il mio programma è l'ultimo che mi tiene legato a zio bill, ho deciso di cominciare a migrare verso il pinguino.

in pratice dovrei riprodurre quel programma con gambas riscrivendo tutto il codice e nel frattempo cercare anche di migliorarlo.

il progetto si basa su una form di avvio (serve per inserire username e password, dato che è multiutente) la quale dopo i controlli di rito apre il main a pieno schermo.

non conoscendo gambas ho cominciato il progetto creando singolarmente le form e basandomi sulle librerie qt.

dato che sono all'inizio farei ancora in tempo a ripartire da zero ma con il piede giusto.

attualmente sto utilizzando ubuntu ma il progetto una volta finito dovra girare su kde.

nel manuale di gambas ho letto che addirittura si possono creare form una dentro l'altra, ho anche provato a usare il codice ma mi richiede 2 parametri che non riesco a capire di che si tratta.
Titolo: Re: form child
Inserito da: md9327 - 27 Ottobre 2009, 13:05:41
Tranne che per le Form, ogni controllo grafico ha, per default e obbligatorio, un parametro, ad indicare quale oggetto è il suo parent, ovvero da chi dipende.

Per le form la cosa è diversa, perchè nella libreria è definita come classe a sè stante, quasi una statica.

Però questo non esclude la possibilità di passargli parametri personalizzati, come ad esempio un parent. Il metodo "_new()" è utilizzabile per questa cosa.

Tieni presente che, però, la gestione di questi parametri, non viene effettuata dall'interprete Gambas, perchè non compresi nella propria logica, e quindi questa deve essere implementata da te.

Descrivere qui, in due parole, il concetto e l'uso di una Application è piuttosto complicato. Se puoi perdere qualche ora, ti posso consigliare di scaricarti il mio pgDesigner, e provare a leggerne il codice sorgente.
pgDesigner è costruito sull'oggetto Application, così come ti avevo descritto, che gestisce tutta la parte logica, mentre l'ambiente grafico è a carico dalla MainView, ma sempre sotto il controllo di Application.
Forse troverai il codice un pò incasinato, perchè è stato stravolto per circa 2 anni; nel caso puoi provare a scaricare dal repository la versione 2.0 alpha, che ho piuttosto rivoluzionato e pulito, e a cui stò ancora lavorando.
Se ti interessa, posso consigliarti di capirne la logica iniziale, che parte da un modulo, per l'acquisizione dei parametri di lancio e delle impostazioni di base, poi fà partire una Application, che crea la sua mainview. Da quel punto in poi, è tutta logica di programma. Le form che crea vengono gestite dalll'applicazione, e così via...
Titolo: Re: form child
Inserito da: dex - 30 Ottobre 2009, 21:09:20
md
penso che un esempio dicodice vale + di numerose lezioni.

provo a vedere il tuo programma.
dicevi dei repository canonical per la 2 alpha?
Titolo: Re: form child
Inserito da: md9327 - 01 Novembre 2009, 18:39:36
Sì, il repository è quello della versione che stò sviluppando.

Ad ogni modo, se leggi la doc ufficiale, per ogni oggetto descritto, derivante da Control, è obbligatorio il passaggio di un parametro, che corrisponde all'oggetto che lo contiene (Container).
Tutto ciò è valido, ad eccezione della classe Form.
Però la cosa è possibile comunque realizzarla per le classi Form, utilizzaando il metodo costruttore "_new()", nel quale puoi definire zero o più parametri a tua scelta, che verranno passati nella creazione dell'oggetto.

Ti faccio un semplice esempio...

Ammettiamo che tu abbia creato un oggetto Form, una bella finestrina vuota, su cui lavorare, inserendo poi gli oggetti che ti servono.
All'inizio della classe (praticamente la parte sorgente della Form), dichiari il metodo costruttore, inserendo alcuni parametri:
Codice: [Seleziona]

PUBLIC SUB _new( parent AS Object, OPTIONAL titolo AS String = "" )
...
END

Il metodo costruttore così creato, permette il passaggio di ulteriori nuovi parametri (la Form, come detto, non ne ha manco uno).
Nell'esempio ho definito un parametro Object, e un parametro opzionale di tipo String.
Se, ammettiamo il caso, tu voglia definire la Form come una finestra figlia di un padre noto (di solito la madre è sicura, il padre no...), quando crei l'oggetto, gli passi il "parent", che corrisponde alla Form padre, o qualsiasi altra cosa che ti serve per la sua gestione.
...Il secondo parametro è, ovviamente, un esempio non utile al nostro discorso...
Quindi, nella creazione della tua Form, ad esempio tramite un pulsante, tu avresti questo codice:
Codice: [Seleziona]

PUBLIC SUB Button_Click()
DIM formFiglia AS NEW TuaForm( ME, "Titolo" )
formFiglia.Show()
END

dove con "ME" identifichi la finestra padre.
La logica è applicabile a qualsiasi oggetto, o classe, che tu definisci nella tua applicazione, indipendentemente se grafico o meno.

Ricorda che, comunque, Gambas esegue in sequenza:
1) il costruttore della classe superiore, ovvero la classe Window con cui è struttura Form, e da cui è derivata;
2) il costruttore della tua form.
Nel caso il costruttore della classe superiore preveda parametri, questi devono essere passati come gli ultimi parametri, durante la costruzione della classe.
Un esempio può essere un oggetto Control, che ha come parametro, appunto, l'oggetto che lo contiene:
Codice: [Seleziona]

PUBLIC SUB _new(parent AS Container) 'costruttore di Control
PUBLIC SUB _new(parent AS Object, title AS String, superParent AS Container) 'costruttore della tua Form


Comunque, io direi che un'occhio al wiki, su cui ho scritto qualcosa in merito, non guasterebbe...

Bye
Titolo: Re: form child
Inserito da: dex - 09 Novembre 2009, 12:23:17
@md9327

dopo varie prove ho optato per il tuo primo consiglio "l'array"

ho creato una classe

Codice: [Seleziona]
' Gambas class file
STATIC PUBLIC MyForm AS Object[20]

STATIC PUBLIC FUNCTION InsForm() 'inserisce i form nell'array
 
  DIM i AS Integer
   i = 0

IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
MyForm[0] = m1.MyNaF
ELSE
   FOR EACH MyForm
      IF MyForm[i] = NULL THEN
      MyForm[i] = m1.MyNaF
      STOP EVENT
      RETURN
      END IF
   INC i '
   NEXT
END IF
m1.MyNaF = NULL  
CATCH  
  Message.Error(Error.Text)  
END

STATIC PUBLIC FUNCTION DelForm() 'cancella i form nell'array
 
  DIM i AS Integer
   i = 0

IF (Object.IsValid(MyForm) OR NOT (IsNull(MyForm))) THEN
   FOR EACH MyForm
      IF MyForm[i] = m1.MyNaF THEN
      MyForm[i] = NULL
      END IF
   INC i '
   NEXT
END IF
m1.MyNaF = NULL    
CATCH  
  Message.Error(Error.Text)  
END

STATIC PUBLIC FUNCTION IcoForm() 'nasconde i form
 
  DIM i AS Integer
   i = 0

IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
FMain.Minimized = TRUE
ELSE
   FOR EACH MyForm
      IF MyForm[i] <> NULL THEN
      MyForm[i].hide
      END IF
   INC i '
   NEXT
   FMain.Minimized = TRUE
END IF
CATCH  
  Message.Error(Error.Text)  
 
END

STATIC PUBLIC FUNCTION MaxForm() 'mostra i form
 
  DIM i AS Integer
   i = 0

IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
FMain.Minimized = FALSE
FMain.Maximized = TRUE
ELSE
   FOR EACH MyForm
      IF MyForm[i] <> NULL THEN
      MyForm[i].show
      END IF
   INC i '
   NEXT
   FMain.Minimized = FALSE
   FMain.Maximized = TRUE
END IF
CATCH  
  Message.Error(Error.Text)
END

STATIC PUBLIC FUNCTION CloForm() 'prima della chiusura controlla i form
  DIM ret AS Integer
  DIM i AS Integer
  DIM MyCoF AS Boolean

IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
QUIT
ELSE
   MyCoF = FALSE
   i = 0
   FOR EACH MyForm
      IF MyForm[i] <> NULL THEN
         IF MyForm[i].fasmod = TRUE THEN MyCoF = TRUE 'controlla i form in fase di modifica
      END IF
   INC i '
   NEXT

   IF MyCoF = FALSE THEN 'se nessun form è in fase di modifica chiude
      QUIT
   ELSE
   i = 0
   FOR EACH MyForm
      IF MyForm[i] <> NULL THEN
         IF MyForm[i].fasmod = TRUE THEN
            IF Message.Error(m1.MyNamA & " Hai un form in fase di modifica!!", "Apri Form", "Chiudo") = 1
                  MyForm[i].show
                  STOP EVENT
                  RETURN
               ELSE
                  QUIT
            END IF
         
         END IF
     
      END IF
   INC i '
   NEXT
   END IF
END IF
CATCH  
  Message.Error(Error.Text)  
 
END


nei form

Codice: [Seleziona]
PUBLIC SUB Form_Open()

  m1.MyNaF = Form1
  FMdi.InsForm
END

PUBLIC SUB Form_Close()

  m1.MyNaF = Form1
  FMdi.delForm
  ME.close
CATCH  
  Message.Error(Error.Text)  

END


il tutto funziona, ora devo solo inserire nell'evento iconize del main.

il problema è che non riesco a trovare l'evento iconize, ho provato nel resize ma non funziona mi arriva in ritardo, e cioè quando riduco a icona non succede nulla, quando riapro il main mi nasconde le form.

io uso il main a pieno schermo e non ridimensionabile.
Titolo: Re: form child
Inserito da: md9327 - 12 Novembre 2009, 11:36:03
Se non ricordo male, il metodo è Minimize, o similare...
Al momento non ho possibilità di verificare...
Titolo: Re: form child
Inserito da: dex - 12 Novembre 2009, 21:46:34
si l'evento è minimize.

il problema è come far intercettare al form questo evento.
in resize risponde in ritardo.

cmq ho risolto in un modo un pò ortodosso ma funziona.

appena metto a punto il tutto ho intenzione di pubblicarlo nei progetti in cerca di aiuto, in questo modo altri potranno intervenire e migliorare il codice, altri potrebbero prendere idee per i loro progetti.

md grazie dell'aiuto e alla prossima
Titolo: Re: form child
Inserito da: Ceskho - 12 Novembre 2009, 23:24:05
Se hai risolto ti sarei grato se inserissi [RISOLTO] nel titolo
Titolo: Re: form child
Inserito da: dex - 13 Novembre 2009, 00:47:50
Ceskho

ordina e sarai accontentato.

ps. ne approfitto per chiederti un favore, sul tuo sito volevo scaricare la calcolatrice per inserirla nel mio progetto, ma mi dà sempre errore.

mi passi il link diretto?
Titolo: Re: [RISOLTO]form child
Inserito da: Ceskho - 13 Novembre 2009, 13:54:29
[OT] Sto cambiando il sito di hosting per i file..se attendi poi ti passo il link...

Ok....fatto...vai a questo indirizzo: http://soluzionisoftware.netsons.org/vari.html

lì, nella colonna di destra potrai scaricare i sorgenti della calcolatrice...spero ti torni utile...:-)
[/OT]
Titolo: Re: [RISOLTO]form child
Inserito da: dex - 13 Novembre 2009, 22:15:35
grazie
la inserisco nel mio progetto
Titolo: Re: [RISOLTO]form child
Inserito da: Ceskho - 13 Novembre 2009, 22:18:45
Se vuoi lascia un commento sul blog...;-)
Lo trovi in firma...
Titolo: Re: [RISOLTO]form child
Inserito da: dex - 14 Novembre 2009, 01:07:02
fatto.

ne ho approfittato per lasciarti un suggerimento su alcune modifiche.

ciao