Italian Pagine che compaiono quando non dovrebbero

Vasmar

Member
Licensed User
Buonasera,
ho questo problema per cui con il B4XMainPage, nella sub _Created, chiamo un altro modulo (SParm) che a sua volta compone una sua videata.

B4X:
        Log("PRIMA")
        B4XPages.ShowPage("SParm")
        Wait For (B4XPages.MainPage.SParm.AspettaScelta) Complete(Result As Object)
        Log("DOPO")
Viene eseguito il log "PRIMA" della chiamata ma non quello "DOPO", però la videata che compare è quella del b4xmainpage.
Se poi chiamo di nuovo SParm digitando su un pulsante

B4X:
    B4XPages.ShowPage("SParm")
allora compare la pagina di SParm e posso lavorarci. Poi quando chiudo la pagina SParm compare il log "DOPO".
Come posso fare per far comparire subito la pagina chiamata, e non quella del B4XMainPage?
Grazie :).
 

Elric

Well-Known Member
Licensed User
Non è che ho capito bene.

Poi, senza sapere cosa c'è dentro la sub AspettaScelta, si fa fatica. Peraltro, se hai definito SParm, puoi accedervi direttamente con SParm.AspettaScelta. è Normale che il log "Dopo" compaia dopo che il Wait For ha finito di far e il suo lavoro. Ma scritto così fa un po' di confusione.

Mi pare di aver capito il tuo desiderio è che si veda la pagina SParm appena l'app parta e solo dopo una qualche scelta dentro SParm si veda la B4XMainPage. Se ho capito bene, prova a impostare la B4XMainPage così:
B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private SParm As pSParm
    Private intAppearing as Int ' educational purposes variable
    Private intDisappearing as Int ' educational purposes variable
End Sub

Public Sub Initialize
    Log($"MainPage: Initialize"$)
    B4XPages.GetManager.TransitionAnimationDuration = 0
  
    SParm.Initialize
    B4XPages.AddPageAndCreate("SParm", SParm) 'add this page immediately and before to display the MainPage
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Log($"MainPage: B4XPage_Created"$)
    Root = Root1
    Root.LoadLayout("MainPage")
  
End Sub

'This event will be called once, clicking on "back" or "x" button.
Private Sub B4XPage_CloseRequest As ResumableSub
    Log($"MainPage: B4XPage_CloseRequest"$)
    B4XPages.ShowPageAndRemovePreviousPages("SParm")
    Return True
End Sub

'This event will be called any time this page appear.
Private Sub B4XPage_Appear
    Log($"MainPage: B4XPage_Appear"$)
    intAppearing = intAppearing + 1
    Log($"This Page appears ${intAppearing} time(s)"$)
End Sub

'This event will be called any time this page disappear.
Private Sub B4XPage_Disappear
    Log("MainPage: B4XPage_Disappear")
    intDisappearing = intDisappearing + 1
    Log($"This Page disappears ${intDisappearing} time(s)"$)
End Sub

Private Sub B4XPage_Background
    Log("MainPage:B4XPage_Background")
End Sub

Private Sub B4XPage_Foreground
    Log("MainPage:B4XPage_Foreground")
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Sub Button1_Click
    B4XPages.ShowPageAndRemovePreviousPages("SParm")
End Sub
 
Last edited:

Vasmar

Member
Licensed User
Grazie,
in AspettaScelta c'è

B4X:
Public Sub AspettaScelta As ResumableSub
    Wait For SceltaEffettuataParm
    B4XPages.ClosePage(Me)
    Return Null
End Sub
e il pulsante di chiusura fa così

B4X:
Private Sub BUsci_Click
'    B4XPages.ClosePage(Me)
    CallSubDelayed2(Me, "SceltaEffettuataParm", Null)
End Sub

L'ipotesi che hai fatto è giusta: vorrei far fare delle scelte prima di cominciare con la pagina "normale".
Ho provato le modifiche che hai detto (anche se non ho capito la funzione) ed effettivamente compare subito la pagina di SParm, però quando chiudo SParm, anziché tornare alla pagina del MainPage, chiude l'app
 

Elric

Well-Known Member
Licensed User
L'ipotesi che hai fatto è giusta: vorrei far fare delle scelte prima di cominciare con la pagina "normale".
Bene: quello è il codice!
Ho provato le modifiche che hai detto (anche se non ho capito la funzione)
È tutto commentato. Ho anche inserito un nuovo commento in riga 14.
ed effettivamente compare subito la pagina di SParm, però quando chiudo SParm, anziché tornare alla pagina del MainPage, chiude l'app
Sarebbe utile sapere che piattaforma stai usando, se B4A, B4J o le altre, che io non uso.

Nella pagina SParm dovresti inserire la sub B4XPage_CloseRequest.

Poiché è una Resumable sub deve sempre prevedere un Return: "Return True", permette che l'app si chiuda, "Return False", impedisce all'app di chiudersi. Qui di seguito un piccolo esempio che potrebbe chiarire meglio:
B4X:
Private Sub B4XPage_CloseRequest As ResumableSub

    'Dim msgAskingToCloseAs Object = xui.Msgbox2Async("Close?", "Title", "Yes", "Cancel", "No", Null)
    'Wait For (msgAskingToClose) Msgbox_Result (Result As Int)
    'If Result = xui.DialogResponse_Positive Then
    '    Return True
    'End If

    B4XPages.ShowPageAndRemovePreviousPages("MainPage")
    Return False
End Sub
Se usi B4A, questo codice (quello con Return False) torna alla MainPage se premi il tasto back dello smartphone. Se invece usi il testo commentato, prima di compare un messaggio di avviso e se rispondi "Yes" chiude l'app. Se usi B4J, lo stesso comportamento lo hai con il tasto "X" della finestra.

Se preferisci avere un pulsante di chiusura della pagina e vuoi semplicemente tornare alla MainPage o vuoi andare in un altra pagina, devi usare il comando:
B4X:
B4XPages.ShowPageAndRemovePreviousPages(...) ' tra le parentesi l'ID della pagina in cui si vuole andare
quindi, il tuo codice dovrebbe essere:
B4X:
Private Sub BUsci_Click
    B4XPages.ShowPageAndRemovePreviousPages("MainPage")
End Sub

Anche se usi il pulsante di chiusura, ti consiglio di usare sempre la Private Sub B4XPage_CloseRequest, in modo che tu possa gestire meglio il tasto back in B4A o il tasto di chiusura finestra in B4J.

Poi, secondo me non hai capito bene l'uso del Wait For, ma magari mi sbaglio. Se fossi in te ripasserei/studierei https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/, gli altri tutorial https://www.b4x.com/etp.html e i booklet https://www.b4x.com/android/documentation.html.

Wait for ti serve per bloccare l'esecuzione delle righe successive. Ma non ti serve quando l'app ha fatto tutto quello che deve fare e attende il comando dell'utente.

Se attendi una risposta dalla rete che potrebbe impiegare qualche secondo, oppure se hai un ciclo con iterazioni molto pesante o vuoi essere sicuro che tutte le tue variabili siano inizializzate prima di caricare un layout, per evitare che l'algoritmo vada avanti ci metti un Wait For. Guarda l'esempio che ti ho fatto sopra per la B4XPage_CloseRequest: se premi il tasto back dello smartphone o il tasto "X" di chiusura finestra, la sub si attiva e andrebbe avanti ma con il Wait For usato per caricare un messaggio è costretta a fermare l'esecuzione e attendere che l'utente risponda al messaggio prima di andare avanti.
 

LucaMs

Expert
Licensed User
Longtime User
Premetto che ho letto solo il primo post ed anche piuttosto velocemente.

Le B4XPage_Created vanno trattate coi guanti, in modo particolare, si deve sempre farle completare prima di eseguire chiamate "particolari". Vanno "viste" come se in realtà la pagina non sia stata veramente e completamente creata (a maggior ragione quella della B4XMainPage), come se fossero la Sub Initialize (ed infatti è prassi comune inizializzare variabili in quel punto, benché a me non piaccia, il posto più adatto è proprio la Sub Initialize stessa).

Al loro interno sconsiglio vivamente di usare "Wait For" e "Sleep", dato che questi comandi fanno "uscire il flusso da quella Sub e lo fanno rientrare in seguito".
E' perfino meglio eseguire chiamate usando CallSubDelayed [-2-3] dal loro interno, in modo tale che la Sub chiamata venga eseguita solo al completamento di B4XPage_Created.
 
Last edited:

Vasmar

Member
Licensed User
Grazie Elric, studierò e (forse) capirò meglio, proverò ad aggiungere quanto suggerito.
Grazie LucaMs (Ms sta per "Mezzo sparito"? 🤭), seguirò il tuo consiglio.
 
Top