Gambas-it

Gambas3 => Programmazione => Topic aperto da: Gianluigi - 27 Novembre 2018, 16:21:32

Titolo: Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 27 Novembre 2018, 16:21:32
Vedo che ancora tanti postano programmi che per chiudersi usano Quit.
Questa non è affatto buona programmazione.
Un programma grafico va chiuso usando la routine Me.Close della finestra principale e scrivendo nella routine pubblica Form_Close() il codice atto a terminare correttamente il programma.
Impostando la finestra principale così:
Codice: [Seleziona]
Application.MainWindow = Me
otterremo che tutte le finestre del programma attualmente aperte si chiudano insieme alla finestra principale.
Ricapitolando:
All'apertura della finestra principale noi la impostiamo come tale per l'applicativo.
Nella routine Form_Close teniamo conto di tutto quanto il programma ha coinvolto per rilasciarlo correttamente.
In caso di errori sopraggiunti anche all'esterno della finestra principale, se ingestibili altrimenti, invieremo un FMain.Close dopo aver avvisato l'utilizzatore.

Rimango in attesa di vs. gradite precisazioni.
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 27 Novembre 2018, 16:57:03
...infatti, come precisa la documentazione ufficiale di Gambas:

" This instruction is not very successful in freeing things with GUI programs. So you should use it only with console applications. "
http://gambaswiki.org/wiki/lang/quit

" ...la memoria utilizzata sarà liberata nel miglior modo possibile pur non essendo questa operazione garantita. Infatti l'istruzione nasce principalmente per la linea di comando...  "
http://gambaswiki.org/wiki/lang/quit?l=it
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: allegfede - 03 Dicembre 2018, 17:27:09
con buona pace del garbage collector :D

comunque utile precisazione ... si evita di saturare la memoria di aree non liberate (penso)
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 03 Dicembre 2018, 22:43:34
(penso)

In che senso... "penso" ?

 (https://media.giphy.com/media/709Rs1gZVwIIU/giphy.gif)
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: allegfede - 04 Dicembre 2018, 11:56:06
che non so come funziona il garbage collector di linux / gambas .. se la pulizia la fa comunque in background
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 04 Dicembre 2018, 15:33:50
che non so come funziona il garbage collector di linux / gambas .. se la pulizia la fa comunque in background

Leggi qui (http://gambaswiki.org/wiki/def/gc)
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: allegfede - 04 Dicembre 2018, 16:00:54
ooooo kkkey :D
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 18 Novembre 2021, 12:13:23
Ciao a tutti, so che è un topic vecchio, ma io non riesco a far funzionare correttamente questa cosa.
Ho aggiunto "Application.MainWindow = Me" nell'evento Form_Open() della form principale della mia applicazione. La form è di tipo persistent.
La mia applicazione installa un'icona nella tray, con un menù contestuale agganciato.
Se io clicco sulla voce "quit" del menù contestuale della tray icon, viene invocato l'evento mnQuit_Click() il quale dealloca varie risorse, imposta la form principale come NON persistent, rimuove l'icona nella tray e infine chiude la form principale. Questo chiude correttamente l'applicazione.
Se però devo uscire dall'applicazione da un punto diverso del codice, la cosa più pulita mi sembrava quella di invocare esplicitamente mnQuit_Click(). Ma questo non funziona: dopo aver eseguito il codice di mnQuit_Click() e il codice di Form_Close(), l'esecuzione ritorna nel punto in cui avevo chiamato la mnQuit_Click() e continua.

Come devo fare?
Fin'ora, l'unico modo che ho trovato è aggiungere "Quit" sotto "mnQuit_Clic()", ma questo ha tutta una serie di inconvenienti che ben conosciamo.

Ciao
Cris
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 18 Novembre 2021, 12:26:48
Ciao,
dopo la esplicita invocazione  nmQuit_Click() prova a porre un Return:

Codice: [Seleziona]
......

  nmQuit_Click()

  Return

......
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 18 Novembre 2021, 12:37:35
Ciao Vuott

Ciao,
dopo la esplicita invocazione  nmQuit_Click() prova a porre un Return:

Codice: [Seleziona]
......

  nmQuit_Click()

  Return

......

Già provato. Ottengo solo di uscire dalla funzione e ritornare al chiamante, il quale prosegue come se nulla fosse  :'(
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 18 Novembre 2021, 12:49:54
Ciao Vuott

Ciao,
dopo la esplicita invocazione  nmQuit_Click() prova a porre un Return:

Codice: [Seleziona]
......

  nmQuit_Click()

  Return

......

... ritornare al chiamante, il quale prosegue come se nulla fosse
Non riesco a capire, scusami.
Nel mio breve esempio di sopra "nmQuit_Click()" è il chiamante della sottoprocedura-Evento...
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 18 Novembre 2021, 14:48:24
Ciao a tutti, so che è un topic vecchio, ma io non riesco a far funzionare correttamente questa cosa.
Ho aggiunto "Application.MainWindow = Me" nell'evento Form_Open() della form principale della mia applicazione. La form è di tipo persistent.
La mia applicazione installa un'icona nella tray, con un menù contestuale agganciato.
Se io clicco sulla voce "quit" del menù contestuale della tray icon, viene invocato l'evento mnQuit_Click() il quale dealloca varie risorse, imposta la form principale come NON persistent, rimuove l'icona nella tray e infine chiude la form principale. Questo chiude correttamente l'applicazione.
Se però devo uscire dall'applicazione da un punto diverso del codice, la cosa più pulita mi sembrava quella di invocare esplicitamente mnQuit_Click(). Ma questo non funziona: dopo aver eseguito il codice di mnQuit_Click() e il codice di Form_Close(), l'esecuzione ritorna nel punto in cui avevo chiamato la mnQuit_Click() e continua.

Come devo fare?
Fin'ora, l'unico modo che ho trovato è aggiungere "Quit" sotto "mnQuit_Clic()", ma questo ha tutta una serie di inconvenienti che ben conosciamo.

Ciao
Cris

Per provare ho creato un piccolo esempio e mi sono accorto che, come purtroppo succede ciclicamente, La TrayIcon con Ubuntu non funziona a dovere.
Probabilmente si tratta di un bug, l'ennesimo che affligge questo componente.
Ho segnalato il malfunzionamento sul bugtracker, e penso che lo dovrai fare anche tu.

Per essere sicuro che non sia un tuo errore potresti postare un piccolo esempio che riproduce il malfunzionamento, così possiamo testarlo...

 :ciao:

Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 19 Novembre 2021, 15:40:45
Ora che, malgrado sia febbricitante, Benoit Minisini ha corretto uno dei bug che affliggono la trayicon il progetto allegato su Ubuntu 20.04 con Gambas ultimo Master funziona
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 21 Novembre 2021, 10:22:50
...
Se però devo uscire dall'applicazione da un punto diverso del codice, la cosa più pulita mi sembrava quella di invocare esplicitamente mnQuit_Click(). Ma questo non funziona: dopo aver eseguito il codice di mnQuit_Click() e il codice di Form_Close(), l'esecuzione ritorna nel punto in cui avevo chiamato la mnQuit_Click() e continua.

Come devo fare?
Fin'ora, l'unico modo che ho trovato è aggiungere "Quit" sotto "mnQuit_Clic()", ma questo ha tutta una serie di inconvenienti che ben conosciamo.

Ciao
Cris

Ho modificato l'applicazione allegata al mio post precedente del 19 per adattarla a quanto hai scritto.
Per poterla scaricare occorre collegarsi

 :ciao:
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 22 Novembre 2021, 11:39:13
Ora che, malgrado sia febbricitante, Benoit Minisini ha corretto uno dei bug che affliggono la trayicon il progetto allegato su Ubuntu 20.04 con Gambas ultimo Master funziona

Grazie Gianluigi, mi sai dire che versione contiene la fix per la trayicon?

Ciao
Cris
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 22 Novembre 2021, 12:50:40
Ora che, malgrado sia febbricitante, Benoit Minisini ha corretto uno dei bug che affliggono la trayicon il progetto allegato su Ubuntu 20.04 con Gambas ultimo Master funziona

Grazie Gianluigi, mi sai dire che versione contiene la fix per la trayicon?

Ciao
Cris

Ultima master, ma il mio esempio funziona anche con la stabile.
Solo se hai dei sotto menu potresti avere dei problemi con versioni più datate della master, ma solo con desktop gtk

 :ciao:
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 23 Novembre 2021, 10:14:28
Purtroppo anche con l'ultima master non funziona. E poi il mio problema non è legato alla TrayIcon, infatti il comando Quit dal menù della TrayIcon funziona.
Facciamo che appena ho tempo provo a produrre un programmino che illustri il comportamento anomalo.

Ciao
Cris
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Gianluigi - 23 Novembre 2021, 12:22:43
Purtroppo anche con l'ultima master non funziona. E poi il mio problema non è legato alla TrayIcon, infatti il comando Quit dal menù della TrayIcon funziona.
Facciamo che appena ho tempo provo a produrre un programmino che illustri il comportamento anomalo.

Ciao
Cris

Scusa ma non ho capito, mi stai dicendo che il progetto di esempio che ho allegato a te non funziona?
Perché a me funziona correttamente, quando esco dal programma cliccando sul Pulsante Quit della FMain si chiude anche la trayicon oltre alle finestre aperte.
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 04 Dicembre 2021, 14:59:49
Ciao Gianluigi

Scusa ma non ho capito, mi stai dicendo che il progetto di esempio che ho allegato a te non funziona?
Perché a me funziona correttamente, quando esco dal programma cliccando sul Pulsante Quit della FMain si chiude anche la trayicon oltre alle finestre aperte.

No scusa non sono stato chiaro.
Intendevo solo dire che il mio problema non è risolto. Ma il mio problema è diverso, lo capirete meglio non appena riesco a trovare il tempo per produrre un piccolo programma demo.

Scusate la lungaggine, ma il fatto è che il programma in questione lo posso testare solo in ambiente di lavoro e generalmente durante le ore di lavoro non ho molto tempo libero per dedicarmi a produrre il programma che dimostri il problema.

Ciao
Cris
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 04 Dicembre 2021, 17:43:10
Ok, mi sono preso un momento per mettere giù il programmino.
In realtà ho riutilizzato un altro esempio che avevo mandato a Benoit, che illustra un bug con i sottomenù nella tray.

Ho aggiunto la funzione DoSomething() che, quando si seleziona la voce "entry4" nel TrayMenu, tenta di chiudere il programma con me.Close.

Alcune precisazioni:
- dovete usare il menu TrayMenu nella finestra principale, se invece lo fate usando il menù contestuale della tray icon non funzionerà, per via del bug segnalato precedentemente (a meno che stiate usando una versione recente del branch 3.17)
- il codice così com'è sembra non avere senso, ma ovviamente si tratta solo di un esempio per triggerare il "bug"

Come potrete vedere, quando si sceglie la voce "entry4" il programma si chiude, ma non subito dopo la me.Close, ma solo dopo aver eseguito tutto il codice che può eseguire... in pratica dopo aver esaurito tutto lo stack delle chiamate.

Ora immaginatevi un programma che ha uno stack di chiamate profondo magari 4 o 5 livelli, al 5° livello trova un errore non recuperabile e chiede all'utente se vuole ritentare o meno. L'utente risponde "no" e quindi il programma deve terminare. Ma invece di terminare dopo la me.Close, questo va avanti ad eseguire (o cercare di eseguire) tutto il codice che c'è dopo la Button1_Click() finché ha esaurito tutto lo stack.
L'unico modo per fermarlo lì dove deve essere fermato è inserire una Quit. O almeno io non ho trovato altro modo.

Dove sbaglio?

Ciao
Cristiano
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 05 Dicembre 2021, 00:43:15
quando si sceglie la voce "entry4" il programma si chiude
Un primo reale problema che riscontro è la sollevazione di un "Warning", e più precisamente il seguente:
gbx3 [5476]: warning: circular references detected:
gbx3:     2 DBusConnection

Per eliminare questo avviso, ho dovuto eliminare la sub-routine:
Codice: [Seleziona]
Public Sub Form_Close()
  TrayIcon1.Delete
End
e far distruggere l'Oggetto "TrayIcon1" con la modalità - che tempo fa Gianluigi ci ha insegnato a fare per qualsiasi Oggetto si tratti - assegnandogli il valore "Null".
In questo caso più precisamente:
Codice: [Seleziona]
Public Function DoSomething(i As Integer) As Boolean

  If i = 4 Then
      TrayIcon1 = Null    <=======
    Me.close
    Return True
  Endif
  Return False

End


L'unico modo per fermarlo lì dove deve essere fermato è inserire una Quit. O almeno io non ho trovato altro modo.
Se io pongo l'istruzione "Quit" dopo quella "Me.Close", ottengo almeno due Warning:

gbx3 [8155]: warning: circular references detected:
gbx3:     1 DBusStatusIconMenu
gbx3:     1 DBusStatusIcon
gbx3:     2 DBusConnection
gbx3:     4 DBusObject
gbx3 [8155]: warning: 5 allocation(s) non freed.


Se pongo la sola istruzione "Quit" (quindi senza "Me.Close"), ottengo i medesimi due Warning.

Per ottenere un'uscita "pulita", dopo aver attivato il Componente "gb.signal", devo impostare la sub-routine come segue:
Codice: [Seleziona]
Public Function DoSomething(i As Integer) As Boolean
 
  If i = 4 Then
    Signal.Send(Application.Handle, Signal.SIGKILL)
    Return True
  Endif

  Return False

End
Tale soluzione impedirà al programma di proseguire oltre tale riga del "Signal.Send()".

Al riguardo e più in generale si veda il paragrafo presente in questa pagina della nostra wiki:
   https://www.gambas-it.org/wiki/index.php?title=Chiudere_programmi_esterni#mediante_le_risorse_della_Classe_.22Signal.22_di_Gambas
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: Cris_70 - 05 Dicembre 2021, 15:34:56
Ciao vuott!

Un primo reale problema che riscontro è la sollevazione di un "Warning", e più precisamente il seguente:
gbx3 [5476]: warning: circular references detected:
gbx3:     2 DBusConnection


Si, questo è esattamente il motivo per cui si vuole evitare di usare la "Quit" nei programmi grafici.
O almeno credo, nel senso che, per quanto uno cerchi di deallocare tutto quello che ha allocato, ci sono sempre questi warning all'uscita con Quit. Io non sono mai riuscito ad evitarli, perlomeno.

Per eliminare questo avviso, ho dovuto eliminare la sub-routine:
Codice: [Seleziona]
Public Sub Form_Close()
  TrayIcon1.Delete
End
e far distruggere l'Oggetto "TrayIcon1" con la modalità - che tempo fa Gianluigi ci ha insegnato a fare per qualsiasi Oggetto si tratti - assegnandogli il valore "Null".
In questo caso più precisamente:
Codice: [Seleziona]
Public Function DoSomething(i As Integer) As Boolean

  If i = 4 Then
      TrayIcon1 = Null    <=======
    Me.close
    Return True
  Endif
  Return False

End

Mmm, si ok così funzionerà anche ma non è ottimale. Non funziona allo stesso modo se invece l'istruzione
TrayIcon1 = Null
la metti nella Form_Close()? (Non ho provato, più tardi lo faccio)

Rimane poi il problema degli altri warning.

Per ottenere un'uscita "pulita", dopo aver attivato il Componente "gb.signal", devo impostare la sub-routine come segue:
Codice: [Seleziona]
Public Function DoSomething(i As Integer) As Boolean
 
  If i = 4 Then
    Signal.Send(Application.Handle, Signal.SIGKILL)
    Return True
  Endif

  Return False

End
Tale soluzione impedirà al programma di proseguire oltre tale riga del "Signal.Send()".

Si ok, ma così stai dicendo al sistema operativo di killare il tuo stesso programma. Eviterà anche i warning, ma non lo chiamerei un'scita "pulita".

In ogni caso, il punto che qui volevo sollevare è che l'indicazione di usare la chiusura della form principale come metodo di uscita non funziona. O almeno non funziona sempre.
Credo che questa sia una mancanza piuttosto grave, a cui si dovrebbe trovare un rimedio più "architetturale" (==> Benoit?).

E poi: perché quando faccio click sul pulsante di chiusura il programma esce senza warning, mentre quando esco con Quit dopo aver chiuso la form principale ho dei warning? Alla fine, il codice di deallocazione che viene eseguito è lo stesso.

Ciao
Cris
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 30 Dicembre 2021, 20:14:22
Non funziona allo stesso modo se invece l'istruzione
TrayIcon1 = Null
la metti nella Form_Close()?
Dunque funziona ugualmente se quell'istruzione la metti nella routine del Metodo nascosto "_free()":
Codice: [Seleziona]
Public Sub _free()

    TrayIcon1 = Null

End
Puoi usare anche quest'altra istruzione:
Codice: [Seleziona]
Free(Object.Address(TrayIcon1))
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: spheris5 - 06 Febbraio 2022, 21:28:45
Uso spesso il comando QUIT perché il mio programma non si chiude correttamente con me.close.
Una funzione mal programmata, un errore nel codice e la mia applicazione non si chiude. Il comando QUIT è magico.
quindi continuo ad usarlo.
Titolo: Re:Come si esce correttamente da un programma grafico?
Inserito da: vuott - 06 Febbraio 2022, 22:17:55
Certo, però, come dice l'avvertenza nella wiki ufficiale di Gambas:
   https://gambaswiki.org/wiki/lang/quit?l=it
l'uso dell'istruzione "Quit" in ambiente grafico, non è una soluzione molto ortodossa.