Spanish Código que funciona bien hasta repetir otro intento. Errores java.

ngr888

Member
Hola.
Tengo el siguiente código con el que pretendo (muchas veces, de forma cíclica), recoger la entrada de tres números entre 1 y 5 cada uno (sin repetirlos).
Luego componer un número de tres cifras con las entradas almacenadas en tres etiquetas y en un vector e(3).
Para ello he dispuesto una Activity con tres etiquetas que recogerán una única cifra. Otra etiqueta para mostrar la “Salida” (o Solución).
Cinco botones con Nombre, Tag y Texto: btnN1, 1 , 1…btnN2, 2, 2 etc con btnEvent. Un botón más para iniciar una nueva entrada: OTRA.
Y un botón CUARTO para mostrar la salida (no quiero que el resultado se vea de inmediato)
El programa compila bien tanto en modo DEBUG como en modo RELEASE. No hay ningún mensaje de error ni advertencia alguna.
Al ejecutarlo en el móvil funciona todo bien en el primer intento, como se esperaba. Salvo que no se muestran unas sentencias log() que he intercalado en el código a modo de control del flujo.
Pero al querer repetir ese proceso en un nuevo ciclo, con el botón OTRA, para recoger nuevos datos, todo se descompone:
En la ventana LOGs aparecen un montón de líneas con avisos de error (java) que he copiado.
El terminal deja de funcionar (se bloquea) y no puedo acceder a ningún otro lugar, ni para cerrar el programa. Tengo que reiniciar el móvil.
El PC con el IDE no está conectado a la red. La depuración se hace vía USB, pero eso ha funcionado con otros programas.
Se pretende ampliar el programa con otras rutinas posteriores. La salida es solamente una prueba.
¿Qué hago mal? ¿Alguna sugerencia? Gracias.
B4X:
#Region Project Attributes 
  #ApplicationLabel: NUM_5_02
  #VersionCode: 1
  #VersionName:
  'SupportedOrientations possible values: unspecified, landscape or portrait. 
  #SupportedOrientations: unspecified
  #CanInstallToExternalStorage: False
#End Region

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

Sub Process_Globals
  'These global variables will be declared once when the application starts.
  'These variables can be accessed from all modules.
  Private xui As XUI
End Sub

Sub Globals
  'These global variables will be redeclared each time the activity is created.
  Private btnN1 As Button
  Private btnN2 As Button
  Private btnN3 As Button
  Private btnN4 As Button
  Private btnN5 As Button
  Private btnOtra As Button
  Private btnSalida As Button
  Private lblN1 As Label
  Private lblN2 As Label
  Private lblN3 As Label
  Private lblSalida As Label
  Private e(3) As Int
  Private nPartida = 0 As Int
  Private QueEtiqueta = 0 As Int
  Dim i As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
  Activity.LoadLayout("Layout")
End Sub

Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub

Private Sub btnOtra_Click
  'nPartida = nPartida + 1 ' de momento no se usa
  QueEtiqueta = 0

  ' Subrutina para limpiar textos y activar botones
  Preparar

  ' Dónde enviar cada entrada
  Log(" P R E P A R A D O ++++++++++++")

  ' Recoger 3 entradas
  For i = 1 To 3
    btnEvent_Click
  Next

Log("++++++++++++++++++++++++++++++++++")
Log("YA hay tres valores en e(0 - 1 - 2")
Log("++++++++++++++++++++++++++++++++++")
End Sub

Private Sub btnEvent_Click
  Private btnSender As Button
  btnSender = Sender
  QueEtiqueta = QueEtiqueta + 1

' Luckily there are only three... (but 30?)
  Select QueEtiqueta
    Case 1
      lblN1.Text = btnSender.Text
      e(0) = btnSender.Text
    Case 2
      lblN2.Text = btnSender.Text
      e(1) = btnSender.Text
    Case 3
      lblN3.Text = btnSender.Text
      e(2) = btnSender.Text
  End Select

  ' I do't want to repeat buttons
  btnSender.Enabled = False

  ' Three values naw. End of entry part.
  ' Desactivar TODOS los botones
  ' If QueEtiqueta > 3 Then FinEntrada = True 'And other code...

  If QueEtiqueta = 3 Then
    Limpiar              ' Return ' Ya hay tres entradas
  End If
End Sub

Sub Preparar
  lblN1.Text = ""
  lblN2.Text = ""
  lblN3.Text = ""
  lblSalida.Text = ""
  btnN1.Enabled = True
  btnN2.Enabled = True
  btnN3.Enabled = True
  btnN4.Enabled = True 
  btnN5.Enabled = True
End Sub

Sub Limpiar 
  btnN1.Enabled = False 
  btnN2.Enabled = False 
  btnN3.Enabled = False 
  btnN4.Enabled = False 
  btnN5.Enabled = False
End Sub 

Private Sub btnSalida_Click
  ' La solución será más compleja. De momento vale esto
  ' como número de tres cifras entre 123 y 543 (sin repetir).

  lblSalida.Text= e(0) & e(1) & e(2)
End Sub
 

Rubsanpe

Active Member
Licensed User
Hola. En tu codigo usas un bucle que llama a btnEvent_Click varias veces y en esa función preguntas por el boton pulsado, cuando realmente no se ha pulsado nada y por lo tanto no puede devolverte el boton... Creo que estas haciendo trampas al solitario ;)

Rubén
 

DonManfred

Expert
Licensed User
Longtime User
For i = 1 To 3 btnEvent_Click Next
This does not work. The Eventsub is called by the system.

In your case you are calling this method but inside btnEvent_click you can not get the correct Button with SENDER.
 

ngr888

Member
Hola. Gracias por las respuestas.
Abajo copio los logs que emite el programa, que me resultan totalmente extraños.

El bucle FOR ... NEXT, solicitando tres entradas, funciona bien la primera vez. Se recogen las tres entradas requeridas y los valores devueltos se guardan correctamente tanto el las lbl como en el vector e(...).
También funciona el evento posterior del botón Salida, mostrando el resultado esperado.

Hasta aquí todo es correcto.

Pero... es al pulsar OTRA por segunda vez, cuando falla el código.

Una pista que tal vez ayude, justo antes de bloquearse todo, aparece por un instante el texto OTRA en la etiqueta que debería recibir el primer número por "segunda vez". Parece como si el text del botón se enviase a esa 1a etiqueta que realmente es para procesar un número. Como si se intentase:

e(0) = btnOtra.txt --> tipo Int y tipo String. respectivamente.

Lo que daría un error de tipos no coincidentes.

Me despista que se envíe ese texto fuera del bucle FOR ... NEXT.

En el Diseñador los btnN1 hasta 5 tienen como evento btnEvent.
Los botones btnOtra y btnSalida tienen como evento sus propios nombres, con lo que no deberían responder al "btnEvent" (?).

Mi experiencia en B4A es de sólo unos días leyendo manuales. Este es realmente mi primer intento de programa sin guía.

Gracias por vuestra atención.

=================================
SALIDA DE LOGs que emite el compilador.

B4X:
Copying updated assets files (1)
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Error occurred on line: 79 (Main)
java.lang.NumberFormatException: Invalid double: "OTRA"
  at java.lang.StringToReal.invalidReal(StringToReal.java:63)
  at java.lang.StringToReal.parseDouble(StringToReal.java:269)
  at java.lang.Double.parseDouble(Double.java:295)
  at b4a.NUM_5_02.main._btnevent_click(main.java:453)
  at b4a.NUM_5_02.main._btnotra_click(main.java:536)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:525)
  at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
  at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
  at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:525)
  at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
  at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
  at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
  at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
  at android.view.View.performClick(View.java:4421)
  at android.view.View$PerformClick.run(View.java:17903)
  at android.os.Handler.handleCallback(Handler.java:730)
  at android.os.Handler.dispatchMessage(Handler.java:92)
  at android.os.Looper.loop(Looper.java:213)
  at android.app.ActivityThread.main(ActivityThread.java:5225)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:525)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
  at dalvik.system.NativeStart.main(Native Method)
** Activity (main) Pause, UserClosed = true **
 

Rubsanpe

Active Member
Licensed User
El bucle FOR ... NEXT, solicitando tres entradas, funciona bien la primera vez
El bucle no lo estas usando bien. No se que hace que creas que es correcto. Llamas a la funcion del evento manualmente sin usar un botón para generar el evento, luego Sender no puede estar apuntando a ningun botón y no puedes obtener sus propiedades. Sender deberia contener el objeto generador del evento, y no es el caso.

El error del log lo que te esta diciendo es que estas intentando convertir un valor no numerico en un número. Al no usar un botón para generar el evento y utilizar Sender creo que se esta usando el ultimo que pulsaste ("OTRA").

Rubén
 

ngr888

Member
Hola, Rubén.
El código funcionaría si no utilizase el programa más que una sola vez (de usar y tirar). Eso me hace pensar que la parte del bucle sí funciona. Pero, como dije, mi experiencia en B4A es prácticamente nula. Supongo que estaré confundido, como dices.

EL caso es que si ejecuto el programa una vez, funcion. Si le cierro y le vuelvo a utilizar, funciona... Es decir, se recogen los tres datos numéricos pertinentes, cada uno en su casilla -lblN- a través del bucle; en ese momento los cinco botones de números están deshabilitados, y el botón SALIDA muestra el resultado adecuado.

Eso me hace pensar que se trata de un problema de "refresco", antes de usarle por veces sucesivas.

En cualquier caso no sabría conseguir cómo hacerlo de otra manera, salvo repetir una rutina independiente para cada entrada.

Probaré.
Gracias.
 

ngr888

Member
Unas capturas (si es que acierto a subirlas)
 

Attachments

  • N5_1_Iniciado.jpg
    N5_1_Iniciado.jpg
    14 KB · Views: 114
  • N5_2_1a entrada.jpg
    N5_2_1a entrada.jpg
    20.3 KB · Views: 100
  • N5_3_2a entrada.jpg
    N5_3_2a entrada.jpg
    18.6 KB · Views: 105
  • N5_4_3a entrada.jpg
    N5_4_3a entrada.jpg
    23 KB · Views: 101
  • N5_5_Resultado correcto.jpg
    N5_5_Resultado correcto.jpg
    36.3 KB · Views: 113

josejad

Expert
Licensed User
Longtime User
El código funcionaría si no utilizase el programa más que una sola vez (de usar y tirar). Eso me hace pensar que la parte del bucle sí funciona

Hola:

Creo que la afirmación "la parte del bucle sí funciona" no es del todo correcta. Más bien parece que "la parte del bucle sí funciona la primera vez"...
Siempre la manera más fácil de que te podamos ayudar, es subir el proyecto, de esta forma la gente puede "toquetearlo" y es más fácil ayudar que intentar averiguar qué es lo que pasa, y no haya que crear un proyecto para probar.

Normalmente, en la programación dirigida por eventos, hay que esperar a que esos eventos ocurran, no forzarlos. En este caso estás forzando el evento click del botón, y como bien han comentado los compañeros, por tanto no hay ningún "Sender".
El error te lo está marcando la línea 79 (no sabemos exactamente cual es, pero tú puedes verlo en tu código) y como dice Rubsanpe, estás tratando en algún sitio un string como un número.

No sabría conseguir cómo hacerlo de otra manera, salvo repetir una rutina independiente para cada entrada.
Si no me equivoco, la forma normal de hacerlo sería simplemente mostrar un mensaje o tener una etiqueta que indique: "Seleccione tres números", y la persona va pulsando en ellos y se va deshabilitando el botón correspondiente. Una vez que has capturado que se han pulsado 3 números (por ej. una variable CuantasEtiquetas), entonces llamas a la sub que muestre el resultado.

saludos,
 
Last edited:

Rubsanpe

Active Member
Licensed User
Hola de nuevo. Haz una cosa muy simple. Elimina o comenta el bucle y vuelve a probar. El programa funciona la primera vez porque pulsas los correspondientes botones. El lío está cuando pulsas el botón Otra cuyo evento contiene el bucle.

Rubén
 

ngr888

Member
This does not work. The Eventsub is called by the system.

Hi, DonManfred.
My experience and knowledge of B4X are practically nil.

I don't know how the inner workings of SENDER are designed, but calling "btnEvent_Click" from line of code does work; even inside the For...Next loop.

It is possible that by calling the event in this way, without having done it from a physical button, SENDER is waiting for a button to be pressed. Something like that:
B4X:
Private Sub btnEvent_Click
  dim btnAny As Button
  btnAny = Sender

  ' If Sender = Null Then Wait for
  '     btnAny_Pressed (or something similar to).
  ' Later...

  lblN1.Text = btnAny.Text  ' etc
...
End Sub

The second mystery is, why does an error occur when trying the same thing for the SECOND time?

I have used this technique of firing an event from the code, with success, in programs made in VisualBasic.

I would appreciate any help or clarification on this, as I am perplexed and confused after hearing that this cannot work, when it is empirically true that it does (a few pictures in this thread).

Thanks for your time.
Greetings.
 

Rubsanpe

Active Member
Licensed User
Bien. Veo que no haces ni caso. B4A no es Visual Basic.
The second mystery is, why does an error occur when trying the same thing for the SECOND time?
¿Quizas por que esa segunda vez usas un evento que no has usado cuando se ejecuta bien la primera vez?

SENDER is waiting for a button to be pressed.
No es cierto. Sender simplemente guarda el ultimo boton que has pulsado, no espera a que pulses nada. Repito ya por ultima vez. El error esta en en el evento que has creado para el botón OTRA. En ese momento Sender tiene asignado ese boton y cuando intentas convertir su nombre a numero te da el error. Si eliminas el bucle, que no tiene ningun sentido, todo debe funcionar como cuando ejecutas por primera vez el programa.

Ya no digo nada mas sobre este asunto.

Rubén
 

ngr888

Member
Hola de nuevo. Haz una cosa muy simple. Elimina o comenta el bucle y vuelve a probar. El programa funciona la primera vez porque pulsas los correspondientes botones. El lío está cuando pulsas el botón Otra cuyo evento contiene el bucle.

Rubén
Pues sí, llevas (lleváis) razón...
 

ngr888

Member
Probably because you did not set QueEtiqueta = 0 before running the code a 2nd time

Zeroing that variable is the first thing I do in the OTRA routine.

B4X:
Private Sub btnOtra_Click
  'nPartida = nPartida + 1 ' de momento no se usa
  QueEtiqueta = 0

It seems that the wrong thing is to force the firing of the event without being necessary.

Doy las gracias a todos y, por mi parte, doy el tema por resuelto.
 
Top