B4J Question Strange error: ...Canvas cannot be cast to ...Pane

LucaMs

Expert
Licensed User
Longtime User
Sub Test:
pnContainer, "a B4XView Pane", contains 6 "B4XView Panes".
The first time you call this Sub, no errors; the second time, it throws the casting exception as per the title of this thread, for the first Pane contained, Pane2.

Sub Test2:
It works without error.

B4X:
Private Sub Test
    For Each xView As B4XView In pnContainer.GetAllViewsRecursive
        Log(xView.Tag)
        Dim xCanvas As B4XCanvas
        xCanvas.Initialize(xView)
        xCanvas.Release
    Next
End Sub

B4X:
Private Sub Test2
    Log("Test2")
    Dim xCanvas As B4XCanvas
    xCanvas.Initialize(Pane2)
    xCanvas.Release
  
    Dim xCanvas As B4XCanvas
    xCanvas.Initialize(Pane2)
    xCanvas.Release
End Sub
 

Attachments

  • CanvasErr.zip
    2.3 KB · Views: 55
Last edited:

PaulMeuris

Active Member
Licensed User
This code doesn't give an error.
No error:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private Pane1 As Pane
    Private Pane2 As Pane
    Private Pane3 As Pane
    Private Pane4 As Pane
    Private Pane5 As Pane
    Private Pane6 As Pane
    Private Pane7 As Pane
    Private pncontainer As Pane
End Sub
Public Sub Initialize
    B4XPages.GetManager.LogEvents = True
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    Test
    Root.LoadLayout("MainPage")
    Test
    Test2
End Sub
Private Sub Test
    For Each xView As B4XView In pncontainer.GetAllViewsRecursive
        Log(xView.Tag)
        Dim xCanvas As B4XCanvas
        xCanvas.Initialize(xView)
        xCanvas.Release
    Next
End Sub
Private Sub Test2
    Log("Test2")
    Dim xCanvas As B4XCanvas
    xCanvas.Initialize(Pane2)
    xCanvas.Release
 
    Dim xCanvas As B4XCanvas
    xCanvas.Initialize(Pane2)
    xCanvas.Release
End Sub
The log lines:
Waiting for debugger to connect...
Program started.
*** mainpage: B4XPage_Created
Pane1
Pane2
Pane3
Pane4
Pane5
Pane6
Pane7
Pane1
Pane2
Pane3
Pane4
Pane5
Pane6
Pane7
Test2
*** mainpage: B4XPage_Appear
*** mainpage: B4XPage_Resize [mainpage]
Maybe because of this:
1670907752094.png

1670907923277.png

Happy coding!
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
As PaulMeuris mentiones, the problem is that in B4J a Canvas is a View on its own.
I have modified your Test routine like below to log the xView type.:
B4X:
Private Sub Test
    For Each xView As B4XView In pnContainer.GetAllViewsRecursive
        Log(xView.Tag)
        Log(GetType(xView))
        Dim xCanvas As B4XCanvas
        xCanvas.Initialize(xView)
        xCanvas.Release
    Next
End Sub
And in the result you see that at the second run you get a javafx.scene.canvas.Canvas object, which cannot be
xCanvas.Release does nothing in B4J nor in B4A.

Waiting for debugger to connect...
Program started.
Pane 2
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 3
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 4
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 5
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 6
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 7
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Pane 2
anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
javafx.scene.canvas.Canvas

What do you expect with this routine ?
You define different B4XCanvases with the same name.
Where and how do you want to use these B4XCanavases ?
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
And in the result you see that at the second run you get a javafx.scene.canvas.Canvas object, which cannot be
Ok but the second time the views and their types, of course, are the same.
Even their number, 6, is the same, the second time (at least apparently); adding:
B4X:
Log("NumberOfViews: " & pnContainer.NumberOfViews)
you get 6 both times.

If you remove all views before calling Test the second time, no exception will be raised.
B4X:
Private Sub Test
    Log("NumberOfViews: " & pnContainer.NumberOfViews)
    pnContainer.RemoveAllViews
    MainForm.RootPane.LoadLayout("Layout1")
Obviously I would load a layout into the pnContainer; here I do it like this to still have Button1.


In B4A that "project" works without the need to remove views.
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
Ok but the second time the views and their types, of course, are the same.
Even their number, 6, is the same, the second time (at least apparently); adding:
B4X:
Log("NumberOfViews: " & pnContainer.NumberOfViews)
you get 6 both times.
Because the Canvases are childs Panes and not of pnContainer.
With
For Each xView As B4XView In pnContainer.GetAllViewsRecursive
you get also the children of Pane2.

Add Log(Pane2.NumberOfViews) in the routine below.
B4X:
Private Sub Test
    Log(pnContainer.NumberOfViews)
    For Each xView As B4XView In pnContainer.GetAllViewsRecursive
        Log(Pane2.NumberOfViews)
        Log(xView.Tag)
        Log(GetType(xView))
        Dim xCanvas As B4XCanvas
        xCanvas.Initialize(xView)
        xCanvas.Release
    Next
End Sub
At the second run you will see that Pane2 has one view !
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Yep, that's the problem anyway.
Even considering that B4J handles B4XCanvas differently (and in fact with B4A there is no error), I don't understand why that exception is triggered in the second run but not in the first.
java.lang.ClassCastException: javafx.scene.canvas.Canvas cannot be cast to javafx.scene.layout.Pane

Erel, can you say something? :)
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Try my understanding:

In B4J B4XCanvas is a view, so xCanvas.Initialize(xView) will create a canvas view then add it to pane, which here is the xView. The second run pnContainer.GetAllViewsRecursive will get the canvas added in first run as xView, so xCanvas.Initialize(xView) will create another canvas but it can't be added to xView, as this xView is actually a canvas, it tried to cast it to pane as it asks for a pane parameter but it can't cast the canvas to a pane, hence "java.lang.ClassCastException: javafx.scene.canvas.Canvas cannot be cast to javafx.scene.layout.Pane"

in B4A B4XCanvas is not a view. Internally it gets the view's GraphicContext something.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
All this gives me problems, due to my poor memory :confused:

The purpose of B4XCanvas is obviously to try to make our source code as compatible as possible with the 3 "languages", B4A, B4J and B4I, otherwise it would not have been created, since the Canvases already exist for each of these languages.

Is it possible to improve B4XCanvas to avoid these problems?
 
Upvote 0
Top