Android Question B4XPages - Error Declaring Pages

Marcos Alves

Well-Known Member
Licensed User
Hello All,

I have an app in B4XPages with three pages:
- B4XMainPage , pedidos and orderDetail

The app switches from B4XMainPage normally to pedidos ... this is the declaration code in B4XMainPage:
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("loginLayout")
    
    PedidosPage.Initialize
    B4XPages.AddPage("pedidos",PedidosPage)
    
End Sub
Switching to pedidos, the app calls:
B4X:
B4XPages.ShowPageAndRemovePreviousPages("pedidos")
When pedidos is shown, the follow code is called in order to define the orderDetail page:
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    
    Root = Root1
    'load the layout to Root
    Root.LoadLayout("pedidos")
    
    orderDetailPage.Initialize
    B4XPages.AddPage("orderDetail",orderDetailPage)
    
end sub
But when the orderDetailPage is initialized, I'm getting the error (in B4A):

java.lang.ClassCastException: java.lang.NoClassDefFoundError cannot be cast to java.lang.Exception

It's running fine in B4J. I didn't tested in IOS yet. What's wrong? The page definition from B4XMainPage -> pedidos has exactly the same syntax of pedidos -> orderDetail...

Can anybody help me please?
 

LucaMs

Expert
Licensed User
Where orderDetailPage is declared? Seeing how an where you initialize it, you have to declare it in Class_Globals of pedidos.

It is better to declare (as Public), initialize and add all the pages in the B4XMainPage.
 

Marcos Alves

Well-Known Member
Licensed User
Where orderDetailPage is declared? Seeing how an where you initialize it, you have to declare it in Class_Globals of pedidos.

It is better to declare (as Public), initialize and add all the pages in the B4XMainPage.
Hello @LucaMs . orderDetailPage is declared in pedidos Class_Globals as follows:

B4X:
Sub Class_Globals
...
     Private orderDetailPage As orderDetail
...
End Sub
Then, it's initialized in pedidos at B4XPage_Created. It's working on B4J but I'll test to change the declaration and initialization to B4XMainPage module and post the result here...
 

Marcos Alves

Well-Known Member
Licensed User
Where orderDetailPage is declared? Seeing how an where you initialize it, you have to declare it in Class_Globals of pedidos.

It is better to declare (as Public), initialize and add all the pages in the B4XMainPage.
Ok, I still have a problem:

In pedidos module I have a call to a subroutine in orderDetail called "OrderShow":
B4X:
CallSubDelayed2(orderDetailPage,"orderShow",ret)
When orderDetail module was referenced in pedidos the routine orderShow was exposed to it. But declaring orderDetailPage on B4XMainPage I can't reference orderDetail subs anymore... How can I call a sub in orderdetail from pedidos if orderDetailPage as orderDetail is declared only in MainPage module?

Thanks!
 

Marcos Alves

Well-Known Member
Licensed User
B4XPages.MainPage.orderDetailPage.orderShow(ret)
This worked, but I still have a problem. When I call orderDetailPage.Initialize in B4XMainPage, I still have an error as follows:

B4X:
[CODE=b4x]*** Service (starter) Create ***

** Service (starter) Start **

** Activity (main) Create, isFirst = true **

Error occurred on line: 55 (B4XMainPage)

java.lang.reflect.InvocationTargetException

    at java.lang.reflect.Method.invoke(Native Method)

    at anywheresoftware.b4a.keywords.Common.CallSubDebug2(Common.java:1055)

    at com.goLunchStore.b4xpagesmanager._createpageifneeded(b4xpagesmanager.java:1024)

    at com.goLunchStore.b4xpagesmanager._showpage(b4xpagesmanager.java:396)

    at com.goLunchStore.b4xpagesmanager._addpage(b4xpagesmanager.java:224)

    at com.goLunchStore.b4xpagesmanager._addpageandcreate(b4xpagesmanager.java:238)

    at com.goLunchStore.b4xpagesmanager._initialize(b4xpagesmanager.java:162)

    at com.goLunchStore.main._activity_create(main.java:421)

    at java.lang.reflect.Method.invoke(Native Method)

    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)

    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)

    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)

    at java.lang.reflect.Method.invoke(Native Method)

    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)

    at com.goLunchStore.main.afterFirstLayout(main.java:105)

    at com.goLunchStore.main.access$000(main.java:17)

    at com.goLunchStore.main$WaitForLayout.run(main.java:83)

    at android.os.Handler.handleCallback(Handler.java:914)

    at android.os.Handler.dispatchMessage(Handler.java:100)

    at android.os.Looper.loop(Looper.java:224)

    at android.app.ActivityThread.main(ActivityThread.java:7560)

    at java.lang.reflect.Method.invoke(Native Method)

    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)

    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:336)

    at anywheresoftware.b4a.debug.Debug.CallSubNew2(Debug.java:285)

    ... 24 more

Caused by: java.lang.reflect.InvocationTargetException

    at java.lang.reflect.Method.invoke(Native Method)

    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:318)

    ... 25 more

Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Ljavafx/scene/text/Font;

    at java.lang.reflect.Executable.getParameterTypesInternal(Native Method)

    at java.lang.reflect.Method.getParameterTypes(Method.java:186)

    at java.lang.Class.getDeclaredMethods(Class.java:1884)

    at anywheresoftware.b4a.BA.loadHtSubs(BA.java:522)

    at com.goLunchStore.orderdetail.innerInitialize(orderdetail.java:19)

    at com.goLunchStore.orderdetail._initialize(orderdetail.java:68)

    at com.goLunchStore.b4xmainpage._b4xpage_created(b4xmainpage.java:83)

    ... 27 more

Caused by: java.lang.ClassNotFoundException: javafx.scene.text.Font

    ... 34 more
Ok, it looks that there's something wrong in orderDetail Code (or at least something that runs in B4J but not in B4A). But what? The error references the class initialize but not the error inside the class, which is a different behavior if compared with classic B4A... I can't find out what is wrong with this log...

Any suggestion?
 

Marcos Alves

Well-Known Member
Licensed User
B4XPages.MainPage.orderDetailPage.orderShow(ret)
Hello @LucaMs ,

I found the problem. OrderDetail has a java routine in the end to measure multi line text height . This is only required in B4J as is used other libraries in B4A and B4i, but in B4A the compiler is trying to process generating and error. This is the routine:

B4X:
#if Java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javafx.scene.text.Font;
import javafx.scene.text.TextBoundsType;
public static double MeasureMultilineTextHeight(Font f, String text, double width) throws Exception {
  Method m = Class.forName("com.sun.javafx.scene.control.skin.Utils").getDeclaredMethod("computeTextHeight",
  Font.class, String.class, double.class, TextBoundsType.class);
  m.setAccessible(true);
  return (Double)m.invoke(null, f, text, width, TextBoundsType.LOGICAL_VERTICAL_CENTER);
  }
#END IF
I tried to add #IF B4J at the start but didn't work... any suggestion?

Thanks!
 

Marcos Alves

Well-Known Member
Licensed User
Hello @LucaMs ,

I found the problem. OrderDetail has a java routine in the end to measure multi line text height . This is only required in B4J as is used other libraries in B4A and B4i, but in B4A the compiler is trying to process generating and error. This is the routine:

B4X:
#if Java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javafx.scene.text.Font;
import javafx.scene.text.TextBoundsType;
public static double MeasureMultilineTextHeight(Font f, String text, double width) throws Exception {
  Method m = Class.forName("com.sun.javafx.scene.control.skin.Utils").getDeclaredMethod("computeTextHeight",
  Font.class, String.class, double.class, TextBoundsType.class);
  m.setAccessible(true);
  return (Double)m.invoke(null, f, text, width, TextBoundsType.LOGICAL_VERTICAL_CENTER);
  }
#END IF
I tried to add #IF B4J at the start but didn't work... any suggestion?

Thanks!
Sorry @LucaMs , my mistake ! #IF B4J worked !!! 👏 :)
 
Top