Italian Comportamento incomprensibile (Timer / Sender)

zamb

Active Member
Licensed User
Cari amici, sto impazzendo con un comportamento per me del tutto incomprensibile. Mi spego:
Genero da codice un array di labels e con un timer ("cadenza"), caricato con valori random, determino il background ("stimolo") di una di queste labels (random anche questa).
Ad ogni scatto del timer "cadenza" cambio in modo random la label cui imposto il backgroud.
Quando carico il background "stimolo" su una label faccio partire un secondo timer ("durata") caricato con un valore fisso il quale dovrebbe, alla sua scadenza, azzerarmi ("bianco") il backgroud della stessa label.
Vado quindi ad intercettare il click sulle labels e se questo è avvenuto sulla label con lo "stimolo" incremento un contatore e sbianco il background della label cliccata.
Tutto questo funziona non fosse che, anche se clicco sulla label giusta entro il tempo che precede lo scatto del timer "durata", se attivo lo sbiancamento della label dal timer "durata" non intercetto più il click sulla label stessa.
Non capisco più nulla. Ho provato diverse soluzioni ma il risultato non cambia. E' come se il timer "durata" arrivasse comunque prima dell'evento click sulle label.
Mi sembra anche abbastanza assurdo che non si possa puntare ad una label in un array con il suo identificativo (es. label(3)) senza passare dal sender così come non sia possibile creare le labels nel designer per poi farvi riferimento generando una stringa con il suo nome (es stringa = label3) ma questo è un altro discorso.
Di seguito il mio codice nella speranza che qualche anima pia possa illuminarmi.
code:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: False
    #ApplicationLabel: prova
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: false
#End Region

'Activity module
Sub Process_Globals                
     Private eventoTimer As Timer    'x cadenza stimolo
    Private durataTimer As Timer    'x durata stimolo
End Sub

Sub Globals
     Private Label(9) As Label        'array x stimolo
    Private Label10 As Label         'x risultato
    Private stimolo As BitmapDrawable
    Private bianco As BitmapDrawable
    Private intervallo As Int
    Private casella As Byte
    Private contaok As Int = 0
End Sub

Sub Activity_Create(FirstTime As Boolean)
 
    Activity.LoadLayout("1b")
    eventoTimer.Enabled = False                                   'stop di sicurezza x timer stimolo
    durataTimer.Initialize("durataTimer", 500)                    'inizializzo timer x durata stimolo
    durataTimer.Enabled = False                                   'stop x timer durata stimolo
    stimolo.Initialize(LoadBitmap(File.DirAssets, "stimolo.png"))  'carico lo stimolo
    bianco.Initialize(LoadBitmap(File.DirAssets, "bianco.png"))    'carico il bianco
 
    Dim i As Int
    Dim increm As Int

    For i = 0 To 8

        Label(i).Initialize("Label")
     
        If i < 3 Then                      'per label 0,1,2
            increm = i * 32%x
            Activity.AddView(Label(i), 2%x + increm , 20%y, 32%x, 46%x)
            Label(i).Tag = i + 1
        End If
     
        If i > 2 And i <6 Then           'per label 3,4,5
            increm = (i-3) * 32%x
            Activity.AddView(Label(i), 2%x + increm , 20%y + 46%x, 32%x, 46%x)
            Label(i).Tag = i + 1
        End If
     
        If i > 5 Then                    'per label 6,7,8
            increm= (i-6) * 32%x
            Activity.AddView(Label(i), 2%x + increm , 20%y + 92%x, 32%x, 46%x)
            Label(i).Tag = i + 1
        End If
     
    Next
 
    eventoTimer_Tick
         
End Sub

Sub Activity_Resume                  

End Sub


Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub eventoTimer_Tick
    eventoTimer.Enabled = False
    casella = Rnd(0,9)
    Label(casella).enabled = True
    Label(casella).Background = stimolo           'mette lo stimolo in casella (label) random
    durataTimer.Enabled = True                    'attivo timer durata stimolo
End Sub

Sub durataTimer_Tick
    durataTimer.Enabled = False
    Label(casella).Background = bianco                  'sbianco casella stimolo
    'Label(casella).Enabled = False                     'questo inibisce il riconoscimento della label_click xchè la disabilita troppo presto!!!!!
    'casella = -1                                       'tentativo inutile di usare altra strada!!!!!!!!!!!!!!
    intervallo = Rnd(1000,5000)                         'calcolo cadenza stimolo random
    eventoTimer.Initialize("eventoTimer", intervallo)   'inizializzo timer x lo stimolo con tempo random
    eventoTimer.Enabled = True                          'attivo timer stimolo
End Sub


Sub Label_Click

    Dim Send As Label  
    Send = Sender

    Select Case  Send.Tag

        Case 1          
            'If Label(casella).Background = stimolo Then                    'provato non risolve
            If casella = 0 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If
         
        Case 2
            'If Label(casella).Background = stimolo Then                   provato non risolve
            If casella = 1 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok    'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If
         
        Case 3
            'If Label(casella).Background = stimolo Then provato non risolve
            If casella = 2 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If
         
        Case 4
            'If Label(casella).Background = stimolo Then                     provato non risolve
            If casella = 3 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If

        Case 5
            'If Label(casella).Background = stimolo Then                     provato non risolve
            If casella = 4 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If
         
        Case 6
            'If Label(casella).Background = stimolo Then                     provato non risolve
            If casella = 5 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If

        Case 7
            'If Label(casella).Background = stimolo Then                       provato non risolve
            If casella = 6 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If

        Case 8
            'If Label(casella).Background = stimolo Then                     provato non risolve
            If casella = 7 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If

        Case 9
            'If Label(casella).Background = stimolo Then                     provato non risolve
            If casella = 8 Then
                contaok = contaok + 1               'se c'era la stimolo in questa casella incrementa contatore ok
                Label10.Text = "ok = "  & contaok   'e lo visualizza
                Label(casella).Background= bianco   'qui svuota la casella stimolo
                Label(casella).Enabled = False      'disattiva la casella stimolo x evitare conteggi plurimi
            End If

    End Select
 
End Sub

Vi ringrazio in anticipo e mi scuso per la mia ignoranza
Pier
 

LucaMs

Expert
Licensed User
Longtime User
Mi sembra anche abbastanza assurdo che non si possa puntare ad una label in un array con il suo identificativo (es. label(3)) senza passare dal sender
Puoi creare un array che contenga le label ed in questo modo potrai utilizzare tramite l'indice dell'array o, spesso meglio ancora, una Map, così potrai richiamarle addirittura "per nome".
Il primo, l'array, ha d'altra parte il vantaggio che, dichiarandolo di tipo Label, potrai usare direttamente metodi e proprietà dell'elemento dell'array (ovvero l'array è tipizzato, appunto di tipo Label, mentre la Map no).

B4X:
Dim Labels(10) As Label
'...
Labels(5).Text = "..."
oppure

B4X:
Dim mapLabels As Map
mapLabels.Initialize
'...
Dim UnaLabel As Label = mapLabels.Get("LaQuinta")
UnaLabel.Text = "..."
 

LucaMs

Expert
Licensed User
Longtime User
Ah, sto solo leggendo il codice qui sul sito...

Vedo che crei le label a runtime, per i "problemi" che hai esposto (si può fare da Designer...).
Domandina: devi avere una sola label "evidenziata" per volta o anche più d'una?
 

zamb

Active Member
Licensed User
Caro LucaMs, si, mi serve "evidenziare" solo una label per volta.
Per quanto riguarda il tuo suggerimento
Dim Labels(10) As Label
'...
Labels(5).Text = "..."

mi pare di aver provato ma quando generavo il nome random delle label e provavo a puntarle mi sembra che non andasse a buon fine. Ora che ci penso, forse provavo a puntarle come label1,2,3 etc e non come label(1), (2), (3) etc. Non ne sono sicuro e riproverò.

Intanto allego il file zip del progetto come richiesto.

E... i miei complimenti per la solerzia :):)
Grazie
 

Attachments

  • prova.zip
    10 KB · Views: 195

zamb

Active Member
Licensed User
No, no, sono proprio stupido! Sto proprio usando questo modo per generare le label (anche se lo faccio in un loop) e poi le punto come (label(xyz)) e funziona tranne per il problema che descrivevo...
 

LucaMs

Expert
Licensed User
Longtime User
Figurati... in attesa del tuo sorgente, stavo sviluppando tutta una mia versione 😄

Ora non so se "correggerò" il tuo progetto o farò un mix tra il tuo e quanto avevo già scritto... ecco, magari ti allego quanto già scritto, giusto per farti vedere cosa intendevo (poi scarico il tuo e... vedo il da farsi)


Ah, nella Globals metti solo "roba" grafica; le altre variabili mettile nella Process_Globals.
P.S. Tranne i Timer, questi vanno sempre dichiarati nella Process_Globals.
 

Attachments

  • Labels.zip
    9 KB · Views: 204

LucaMs

Expert
Licensed User
Longtime User
Riga 96 del tuo progetto:

eventoTimer.Initialize("eventoTimer", intervallo) 'inizializzo timer x lo stimolo con tempo random

Non si deve reinizializzare eventoTimer ogni volta, basta impostare il suo nuovo intervallo (dopo averlo "fermato")
eventoTimer.Enabled = False
eventoTimer.Interval = intervallo
eventoTimer.Enabled = True
 

LucaMs

Expert
Licensed User
Longtime User
Caro LucaMs, si, mi serve "evidenziare" solo una label per volta.
Questo semplifica le cose.

Dichiara (Globals) una Label, nome tipo: LabelCorrente o simile.

Quando vai a "stimolare" una label, cambiandone lo sfondo:
B4X:
Sub eventoTimer_Tick
    eventoTimer.Enabled = False
    casella = Rnd(0,9)
    LabelCorrente = Label(casella)
    LabelCorrente.Enabled = True
    LabelCorrente.Background = stimolo           'mette lo stimolo in casella (label) random   
    durataTimer.Enabled = True                    'attivo timer durata stimolo   
End Sub

Nelle altre routine, potrai sempre controllare/confrontare le label dell'array con la LabelCorrente.


Pensi sia li il problema?
Non lo so perché ancora non ho letto bene il programma. E' comunque una buona norma da seguire.
 

zamb

Active Member
Licensed User
Scusa, mi sono accorto che debbo necessariamente reinizializzare perchè cambio ogni volta il valore che gli passo (ogni "ciclo" deve avere una "cadenza" diversa)
 

LucaMs

Expert
Licensed User
Longtime User
Scusa, mi sono accorto che debbo necessariamente reinizializzare perchè cambio ogni volta il valore che gli passo (ogni "ciclo" deve avere una "cadenza" diversa)
Non ho capito; normalmente un timer NON si reinizializza. Ho capito che la durata dev'essere random, ma basta impostare questo nuovo valore (la durata dell'intervallo), con:

tmrPippo.Interval = NuovaDurata
 

LucaMs

Expert
Licensed User
Longtime User
Qualcosa tipo il progetto allegato (quasi certamente dovrai/vorrai cambiare lo sfondo di default).

Giusto per darti un'idea sulla gestione delle label e sull'impostarne una "corrente"-"attuale".

C'è anche una Map, messa solo e sempre come esempio, puoi toglierla.
 

Attachments

  • prova.zip
    11.2 KB · Views: 206

zamb

Active Member
Licensed User
Ti ringrazio infinitamente ma evidentemente qualche cosa non va nel tuo codice infatti in fase di assegnazione della label randomizzata facendo un log si evidenzia come, mentre mCasella giustamente evolve in modo randomizzato, non altrettanto succede alla LabelCorrente che resta costante (nel log("labelcorrente" & labelCorrente), vedo delle coordinate che rimangono fisse fregandosene bellamente di mCasella) e costante appare la label con lo stimolo nel background. Purtroppo, date le mie scarse capacità, non riesco a capire dove stia il problema :(
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Da quanto capisco vuoi creare una specie di Simon Game.
i quadretti si colorano e dwci cliccare prima che tornino bianchi.
Per.far.qiesto vuoi intercettare l'evento click e stranamente non ti funziona il riferimento con Sender.

L'approccio del codice a prima vista mi sembra del tutto sbagliato... adesso è tardi ma domani so un occhiata approfondita
 

zamb

Active Member
Licensed User
Hai centrato esattamente quel che voglio fare.
Nel mio codice il click viene intercettato correttamente se non intervengo disabilitando la label con lo stimolo (o sbiancandola) attraverso il timer Durata.
In questo caso però anche se cliccassi fuori tempo massimo, la risposta resterebbe comunque valida in quanto, fino a quando non seleziono un'altra label col timer Cadenza, il sender mi manda l'info che ho cliccato la label corretta. Cosa che non voglio. La risposta deve essere valida solo se arriva anche nel tempo massimo stabilita dal timer Durata.
Per ora ti ringrazio moltissimo per l'interessamento e ti auguro una buona serata.
 
Last edited:

zamb

Active Member
Licensed User
Se può essere utile, ho notato che allungando il timer Durata la cosa funzionicchia nel senso che posso cliccare la casella esatta e questa viene correttamente intercettata purchè il click avvenga non nel corso di tutto il tempo tra la comparsa dello stimolo e la sua cancellazione da parte del timer Durata (tempo teoricamente utile) ma nella prima parte di questo.
Quasi che l'intercettazione attraverso il sender fosse lenta e arrivasse quando già il timer Durata, se breve, ha già cambiato la condizione disabilitando o sbiancando la label. Allungando la Durata invece l'intercettazione avviene (se non clicco troppo avanti nel lasso di tempo teoricamente utile) perchè l'info dal sender riesce ad arrivare in tempo prima che scada la Durata?...)
 

LucaMs

Expert
Licensed User
Longtime User
Ti ringrazio infinitamente ma evidentemente qualche cosa non va nel tuo codice infatti in fase di assegnazione della label randomizzata facendo un log si evidenzia come, mentre mCasella giustamente evolve in modo randomizzato, non altrettanto succede alla LabelCorrente che resta costante (nel log("labelcorrente" & labelCorrente), vedo delle coordinate che rimangono fisse fregandosene bellamente di mCasella) e costante appare la label con lo stimolo nel background. Purtroppo, date le mie scarse capacità, non riesco a capire dove stia il problema :(
mCasella non viene più utilizzato, non serve, perché viene memorizzata in LabelCorrente la Label "stimolata".
Non ho capito perché vuoi disabilitare le Label; se il gioco sta nel fare in tempo a toccare la Label "stimolata" e prendere così un punto, non è necessario disabilitare le altre, in quanto nell'evento Click viene controllato se l'utente abbia toccato la "Label stimolata".

Guarda se ti va bene come allegato; ho cambiato un po' di cose:

1 - usato unico timer
2 - aggiunto log delle label attivata/disattivata
3 - fatto un po' d'ordine nel sorgente
4 - modificato il layout per vedere meglio le label
5 - cambiato modo di calcolare la durata della Label "attiva"
6 - non ricordo cos'altro 😄

Suggerimento: aggiungi una terza Bitmap da assegnare alla Label attiva; se viene toccata la Label quando questa ha il background "giusto" ("stimolata") dai 1 punto ma se ha la terza bitmap, ovvero una che indichi che la Label è quella attiva ma va salvata dal tocco dell'utente, 1 punto in meno.
Nota che per fare questo, dovrai salvare una qualunque variabile a livello globale che indichi quale delle due bitmap sia visualizzata, ovvero label da clickare o label da salvare.

Se ti va bene così, giusto perché sei tu, sono:

50€ + IVA (da donare al link che non vedi nella mia "signature")
10 "Likes" (uno per ogni post).

Se invece non ti va bene... attaccati al tram 😄
 

Attachments

  • prova.zip
    9.9 KB · Views: 209
Last edited:
Top