Grosse difficoltà... :rolleyes:
Allora... ho aggiunto un secondo WorkSpace, in una delle finetre del WorkSpace (nella F3).
In pratica ho ridisegnato la F3, mettendo --> un ToolPanel. Al secondo pannello del ToolPanel ho inserito un Container con dentro due Buttons (btnAggiungi e btnElimina) ed il secondo Workspace (Workspace2).
La sequenza del percorso è --> Work1, F3, Toolpanel (secondo pannello), Work2 & i due Buttons.
Cliccando sul btnAggiungi --> nel Workspace mi viene aggiunto sempre lo stesso form, FX (un form con delle TextBox...).
Per fare questo... nel codice del form F3 ho inserito questo:
Public Sub ButtonX_Click()
Dim i As Integer
Me.Workspace2.Add(Object.New("FX"))
For i = 1 To Me.Workspace2.Children.Count
Me.Workspace2.Children[i - 1].Title = "FX n°" & i
Me.Workspace2.Children[i - 1].Name = "FX" & i
Next
End
Quindi ogni FX che aggiungo dovrebbe avere come Titolo (che compare nel TAB del Workspace2) e Name = "FX n°1" ed "FX1", "FX n°2" ed "FX2", "FX n°3" ed "FX3", ecc.
Invece, cliccando sul btnElimina mi viene eliminata la TAB attiva. Chiaramente mi ricalcola anche i Titoli ed i Nomi, perché se elimino una delle TAB in mezzo, poi si creerebbe un salto di numerazione.
Public Sub Button2_Click()
Dim i As Integer
If Object.IsValid(Me.Workspace2.ActiveWindow) Then 'questo IF serve perché se cliccassi btnElimina con il Workspace vuoto mi restituirebbe giustamente errore...
Me.Workspace2.ActiveWindow.Close
For i = 1 To Me.Workspace2.Children.Count
Me.Workspace2.Children[i - 1].title = "FX n°" & i
Me.Workspace2.Children[i - 1].title = "FX" & i
Next
Endif
End
La domanda è... come faccio a far fare la stessa cosa dal parent? Ossia come faccio a rinumerare e rinominare tutte le TAB se l'eliminazione avviene dalla "x" del TAB anziché dal btnElimina?
PS:
Ho notato una cosa... quando inserisco istanze di FX tramite Me.Workspace2.Add(Object.New("FX"))
in teoria inserisco dei NEW FX, ma sempre con lo stesso nome "FX"? Come fa Gambas a distinguerli? Perché non va in errore? Come faccio io a richiamarne uno anziché un altro?
Come faccio, sempre dal codice di F3, ad inserire del testo nelle txtbox, che si trovano nelle FX che ho creato dinamicamente?
Sto diventando matto appresso a queste cose... :mad: :-\
Però la struttura sta venendo una meraviglia, quindi voglio perseverare finché non arrivo alla soluzione! :coder:
non ho guardato l' esempio di milio e magari mi dico una grossissima str.....a, però io prima di aggiungere un oggetto al workspace gli definerei antecedentemente i parametri principali
Public Sub ButtonX_Click()
Dim i As Integer
Dim tmpobj as fx
tmpobj=new fx
tmpobj.title="FX N°" & me.workspace2.count
tmpobj.name="FX" & me.workspace2.count
Me.Workspace2.Add(tmpobj)
End
immagino che così le tab vengano chiamate in modo corretto e eliminandole rimangano corrette anche qulle rimanenti.
come scritto su , non ho mai usato workspace , il codice è scritto a memoria e magari è una cagata! :)
Milio come sempre sei gentilissimo!
Provo a postarti nei commenti ciò che ho capito del tuo codice, riguardo la FMain:
' Gambas class file
Public DbC As New Connection
Private Paziente As FPazienti 'questo l'ho modificato io... L'ho reso Private perché dopo ne richiamo la textbox1, all'evento "Button1_Click()" (un bottone che ho aggiunto io per fare una prova...)
Public Sub _new() 'qui è semplice... :)
With DbC
.Type = "sqlite3"
.Host = Application.Path
.Name = "pazienti"
End With
With Me.TreeView1
.Add("GPaz", "Gestione Pazienti", Picture["access.png"])
.Add("FPazienti", "Scheda Pazienti", Picture["class.png"], "GPaz")
.Add("NPazienti", "Nuovo Paziente", Picture["new.png"], "GPaz")
End With
End
Public Sub InsPaziente(IdPaziente As Integer) 'qui istanzia un nuovo form FPazienti relativo all'IdPaziente X... che viene ottenuto dall'attivazione della TreeView, e viene aggiunto al WorkSpace
Paziente = New FPazienti(IdPaziente) As "paz"
Me.Workspace1.Add(Paziente)
End
Public Function CercaPaziente(IdPaziente As Integer) As Integer 'qui si fa la ricerca tra i children (le TAB) della WorkSpace, in cui i nomi (che finiscono con un numero) combaciano con IdP...
'Se li trova --> Return Nx ...altrimenti Return -1. Questa operazione serve anche a vedere se l'IdP scelto è già stato aperto (istanziato)...
Dim Nx As Integer
If IdPaziente = -1 Then Return -1
For Nx = 0 To Me.Workspace1.Children.Max
If Me.Workspace1.Children[Nx].Name = "Paziente_" & IdPaziente Then Return Nx
Next
Return -1
End
Public Sub TreeView1_Activate()
Dim Id, IdP As Integer
If TreeView1.Current.Key = "FPazienti" Then 'qui chiede se ho attivato la TV sul pulsante "FPazienti" --> ossia scheda già esistente
IdP = FP.Run() 'se sì --> chiama la funzione pubblica di FP, che si chiama "run" -->
'Questa funzione "run" apre il DB e carica i nomi che ci sono in una combobox (in FP, in showmodal).
'Quando clicchi su "ok" restituisce il valore "id" del paziente... che a sua volta viene restituito a IdP.
'Altrimenti restituisce IdP = -1 (vale a dire che ho cliccato sul tasto "annulla" della FP oppure il TAB del paziente è già aperto)
If IdP = -1 Then Return 'Se IdP = -1 --> non fare niente ...return
Id = CercaPaziente(IdP) 'Id --> chiama la funzione pubblica CercaPaziente(IdP), con l'IdP da cercare, che era stato scelto dalla combobox di prima...
If Id = -1 Then 'se non c'è nessun paziente...
InsPaziente(IdP) '...allora inseriscilo del Database--> tramite InsPaziente(IdP)
Else 'altrimenti...
Me.Workspace1.ActiveWindow = Me.Workspace1.Children[Id] 'attiva la TAB dell'Id già aperto
Endif
Else If TreeView1.Current.Key = "NPazienti" Then 'qui chiede se ho attivato la TV sul pulsante "NPazienti" --> ossia nuova scheda
IdP = FNP.Run() 'se sì --> chiama la funzione pubblica di FNP, che si chiama "run" che restituisce sempre IdP. Altrimenti restituisce IdP = -1 (vale a dire che ho cliccato sul tasto "annulla" della FNP)
If IdP = -1 Then Return 'Se IdP = -1 --> non fare niente ...return
InsPaziente(IdP) '...allora inseriscilo nel Database--> tramite la funzione InsPaziente(IdP)
Endif
End
Public Sub Button1_Click()
Paziente.TextBox1.Text = "Pierino!!!" 'richiama l'oggetto TextBox1 che sta nel form FP e gli cambia una textbox... Quindi da WorkSpace riesco finalmente a cambiare una proprietà di un suo children!
End
Spero di non aver scritto grosse stupidaggini tra i commenti...
Il fatto è che ho capito meglio, ma ancora non mi è chiara una cosa. Nella mia sperimentazione, quando clicco sul bottone (Button1) riesco a cambiare la textbox dell'ultima istanza aggiunta nel WorkSpace. Questo perché l'ultima istanza è "Persona" che è stata dichiarata Private, e che quindi è attiva.
Se invece volessi cambiare la textbox1 di un'altra istanza (una di quelle aperte precedentemente), come la richiamo? Cioè come si richiama un'istanza conoscendone il nome?
PS: il paziente numero 3 è grave! :D
Tutto giusto tranne questa:
Id = CercaPaziente(IdP) 'Id --> chiama la funzione pubblica CercaPaziente(IdP), con l'IdP da cercare, che era stato scelto dalla combobox di prima...
If Id = -1 Then 'se non c'è nessun paziente...
InsPaziente(IdP) '...allora inseriscilo del Database--> tramite InsPaziente(IdP)
Else 'altrimenti...
Me.Workspace1.ActiveWindow = Me.Workspace1.Children[Id] 'attiva la TAB dell'Id già aperto
Endif
InsPaziente(IdP) e' una Sub che inserisce una nuova FormPaziente nel WorkSpace...
Il fatto è che ho capito meglio, ma ancora non mi è chiara una cosa. Nella mia sperimentazione, quando clicco sul bottone (Button1) riesco a cambiare la textbox dell'ultima istanza aggiunta nel WorkSpace. Questo perché l'ultima istanza è "Persona" che è stata dichiarata Private, e che quindi è attiva.
Se invece volessi cambiare la textbox1 di un'altra istanza (una di quelle aperte precedentemente), come la richiamo? Cioè come si richiama un'istanza conoscendone il nome?
Come gia' scritto in qualche post sopra, devi sfruttare la Proprietà WorkSpace.Children[] per richiamare il form che vuoi modificare:
nell'esempio, ad esempio :) , puoi sfruttare l'id Paziente per richiamare il suo form facendo in questo modo:
Public Sub btnCambioSessoSilvio_Click()
Dim FPaz As FPazienti
FPaz = Me.WorkSpace1.Children[CercaPaziente(3)]
FPaz.TextBox4.Text = "F"
End
Con questa riga di codice (naturalmente la scheda di questo paziente deve essere aperta) ho appena cambiato il sesso del Sig. Silvio BungaBunga ;)
Hai perfettamente ragione una è una Sub l'altra una Function...
Ora ho capito! Io avevo provato a fare una cosa simile ma non so perché mi restituiva sempre errore...
Quindi...
Per richiamare l'FPazienti (che deve essere aperto ...ma qui basterebbe fare un controllo) uso la Sub cercapaziente(IdP). Questa restituisce il numero progressivo di TAB aperta nel WorkSpace... una volta attribuita l'istanza FPazienti ad FPaz... posso interaggire con tutti gli oggetti di FPaz!
In pratica questa riga di codice è l'anello di collegamento tra il Work e le sue TAB...
FPaz = Me.WorkSpace1.Children[X]
Stavo pensando che quindi le TAB vengono richiamate per numerica progressiva. Sta a me fare combaciare questo numero al nome del paziente (tu usi un metodo "testuale" --> in pratica aggiungi quel numero progressivo in fondo al nome della tab e poi glielo fai sottrarre in fase di ricerca.
Indi, se volessi modificare il campo "sesso" della TAB attualmente attiva il codice sarebbe simile a questo...
Public Sub Button1_Click()
Dim FPaz As FPazienti
Dim Nx As Integer
For Nx = 0 To Me.Workspace1.Children.Max
If Me.Workspace1.Children[Nx].Name = Me.Workspace1.ActiveWindow.Name Then FPaz = Me.WorkSpace1.Children[nx]
Next
If Me.Workspace1.ActiveWindow.Name = Me.Workspace1.Children[CercaPaziente(3)].Name Then Message.Info("Mi consenta!")
FPaz.TextBox4.Text = "F"
End
Sempre assodato che almeno una TAB sia aperta... ;)
Ho aggiunto nella FPaziente un tetbox5 dove va inserita l'altezza del paziente... Se quindi voglio estrarre i campi "Altezza" di ogni TAB...
Public Sub Button1_Click()
Dim FPaz As FPazienti
Dim Nx As Integer
Dim iAltezza As String
For Nx = 0 To Me.Workspace1.Children.Max
FPaz = Me.WorkSpace1.Children[nx]
If trim(FPaz.TextBox5.Text) <> Null Then
iAltezza &= FPaz.TextBox5.Text & " "
Else
Me.Workspace1.ActiveWindow = Me.Workspace1.Children[Nx]
Message.Warning("Non hai specificato l'altezza di " & Me.Workspace1.Children[Nx].Title & "!")
Return
Endif
Next
iAltezza = Trim(iAltezza)
Message.Info("Le altezze inserite sono: " & iAltezza)
End
Il codice è molto sbrigativo... ma giusto per capire se avevo capito.
Ora credo di aver capito! :2birre: :2birre:
Bene...
Ti mandero' il conto ;D
Indi, se volessi modificare il campo "sesso" della TAB attualmente attiva il codice sarebbe simile a questo...
Per la TAB attualmente attiva, ti basta fare:
Public Sub Button1_Click()
Dim FPaz As FPazienti
FPaz = Me.WorkSpace1.ActiveWindow
FPaz.TextBox4.Text = "F"
End
Comunque si potrebbe anche riprendere in mano il codice del WorkSpace e farci gia' al suo interno delle funzioni di ricerca in cui ti restituisca direttamente, tramite nome oggetto, la form desiderata... mi spiego meglio:
al posto di dichiarare una variabile che mi identifichi la Form come fatto nell'esempio, facendo opportune modifiche basterebbe fare:
ME.WorkSpace[NomeForm].TextBox4.Text = "F"
Che dici, potrebbe essere utile?
Quello che mi hai spiegato tu sul WorkSpace non l'ho trovato scritto da nessuna parte nel web. Credo che bisognerebbe fare una guida
Piano Piano... diciamo che ho imparato bene le basi di gambas, e quindi basta sbirciare il sorgente del componente per rendersi conto di cosa gli si puo' far fare e cosa gli si puo' aggiungere...
magari anche tradotta in inglese
L'inglese? parola a me sconosciuta :P
E se tu agevolassi l'uso del WorkSpace con questa modifica credo che spingeresti anche il WorkSpace ad essere usato di più.
ho scoperto una cosa interessante:
Object.SetProperty(Me.WorkSpace1.Children[0]["TextBox4"], "Text", "F")
In un botto solo ti setto la proprietà Text del TextBox4 del TAB 0 senza dichiarare alcuna variabile ;)
Bingo! :2birre: :2birre:
Sono giorni che ero alla ricerca di un metodo per richiamare direttamente la proprietà "text" dell'oggetto "TextboxX" del "TabX"... Questa è meravigliosa perché non bisogna neppure più istanziare la FPaz... ma basta solo identificare l'Id della Tab...
E quindi, volendo invece ottenere il valore di una proprietà di un oggetto (la proprietà "text" dei campi "nome", ad esempio, della TAB Attiva)...
Object.GetProperty(Me.WorkSpace1.ActiveWindow["TextBox1"], "Text")
:ok:
PS: ho in vaga memoria il fatto che in VB6 usare il codice con SetProperty e/o GetProperty influisse anche sulla velocità di esecuzione dell'azione rispetto alle classiche textbox1.text = "..." oppure nome=textbox1.text. Tu sai qualcosa al riguardo o mi ricordo male io?!
PPS: dove posso scaricare i sorgenti di questi componenti? Oppure sono già nel mio computer in qualche cartella di Gambas3?
[Sorgenti componenti risolto... http://www.gambas-it.org/smf/index.php?topic=438.0 (http://www.gambas-it.org/smf/index.php?topic=438.0)]
Mai cantare vittoria! :hatecomputer: ;D
Questa non credo di poterci arrivare...
Da un Form esterno ho richiamato il .Text di una TextBox1 che si trova nella Tab(0) della WorkSpace1 dell'FMain:
stringa = Object.GetProperty(FMain.Workspace1.Children[0]["TextBox1"], "Text")
Se la TextBox1 è nel Tab(0) --> tutt'ok e mi restituisce il valore...
...ma se la TextBox1 è dentro un toolpanel del Tab(0) il programma va in errore ("Object Null")
Chiaramente la mia TextBox sta dentro un toolpanel.
Per scrupolo ho provato a togliere la TextBox1 da dentro al toolpanel e a metterla in un panel qualsiasi del Tab(0)... e viene letta correttamente.
Non capisco proprio come fare... :rolleyes:
Ho messo un allegato esplicativo... così chi vuol provare capisce meglio la situazione. L'esempio che ho allegato funziona. Ma se andate nel sorgente "Form2" e levate l'apice di commento alla riga10 vedrete che il programma va in errore... L'unica differenza tra le due textbox è che la seconda sta dentro un toolpanel.
I casi sono due:
o hai creato il Form prima di inserirlo nel WorkSpace, come nel tuo caso delle schede pazienti, e quindi conosci la classe genitore FPazienti contenente l'oggetto da aggiornare, allora puoi tornare a fare come avevamo gia' scritto qualche post fa:
Public Sub Button3_Click()
Dim F As FPazienti
If Object.Is(Me.Workspace1.ActiveWindow, "FPazienti") Then
F = Me.Workspace1.ActiveWindow
F.TextBox5.Text = "Ciao!"
Endif
End
Se invece al WorkSpace gli passi un Form direttamente, allora ti basta richiamare l'oggetto normalmente come faresti per un qualsiasi altro Form aperto...
allego solito esempio...