B4J Question [XUI] Question on Canvas initialized with Panel.

Star-Dust

Expert
Licensed User
Longtime User
Creating my example with Bezier curves I noticed something very unusual with the XUI.
I call several times a Sub who redraws an image. Each time draws the image by modifying it with the new parameters.

To give an example, the sub could be like this:
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private PanelMain As B4XView
    Dim xui As XUI 'ignore
End Sub

Private Sub Draw
    PanelMain.RemoveAllViews ' Without this the Canvas does not draw anything, it draws only the first time.
    Dim Can As B4XCanvas
    Can.Initialize(PanelMain)
    
     'Clear old graph
    Dim R As B4XRect
    R.Initialize(0,0,PanelMain.Width,PanelMain.Height)
    Can.DrawRect(R,xui.Color_White,True,1dip)

    Can.DrawCircle(PanelMain.Width/2, PanelMain.Heght/2,rnd(50,200)*1dip,xui.Color_Red,True,1dip)
End Sub
If I did not insert this instruction:
B4X:
PanelB4XView.RemoveAllView
The canvas does not give any results, the image remains the previous one.
Almost as if the image generated previously from the canvas was like a second panel hooked on.
If I release everything (with RemoveAllView), the effect of redrawing can be observed, otherwise it remains the same image.

Can someone enlighten me?
 
Last edited:

klaus

Expert
Licensed User
Longtime User
Declare the canvas only once in Process_Globals and initialize it in AppStart.
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private PanelMain As B4XView
    Private Can As B4XCanvas
    Dim xui As XUI 'ignore
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   MainForm.Show

   Can.Initialize(PanelMain)
End Sud

Private Sub Draw
    Can.DrawCircle(PanelMain.Width/2, PanelMain.Heght/2,rnd(50,200)*1dip,xui.Color_Red,True,1dip)
End Sub
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Yes, I understand, but something like that seems abnormal. Canvas (not B4X) not this flaw.
Erel told me that B4i must release the B4Xcanvas at the end of the job.
B4X:
B4XCavas.Invalidate
B4XCavas.Release

By declaring it global it would not be possible to do so.

It does not cost me anything to add B4AView.RemoveAllView and it's a simpler solution. But it is only to understand the reason
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
PanelMain.RemoveAllViews

Use: Can.ClearRect(Can.TargetRect) and initialize canvas as per @klaus

B4X:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private PanelMain As B4XView
   Dim xui As XUI ' ignore
   Private Can As B4XCanvas
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   Can.Initialize(PanelMain)
   MainForm.Show
   Dim x As Int
   For x = 0 To 10
       Draw
       Sleep(200)
   Next
   Can.Release
End Sub

Private Sub Draw
   'PanelMain.RemoveAllViews ' Without this the Canvas does not draw anything, it draws only the first time.
   'Dim Can As B4XCanvas
   'Can.Initialize(PanelMain)
   Can.ClearRect(Can.TargetRect)
   Can.DrawCircle(PanelMain.Width/2, PanelMain.Height/2,Rnd(50,200)*1dip,xui.Color_Red,True,1dip)
   Can.Invalidate
End Sub
 

Attachments

  • CanvasTest.zip
    1.9 KB · Views: 248
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Use: Can.ClearRect(Can.TargetRect) and initialize canvas as per @klaus

B4X:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private PanelMain As B4XView
   Dim xui As XUI ' ignore
   Private Can As B4XCanvas
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   Can.Initialize(PanelMain)
   MainForm.Show
   Dim x As Int
   For x = 0 To 10
       Draw
       Sleep(200)
   Next
   Can.Release
End Sub

Private Sub Draw
   'PanelMain.RemoveAllViews ' Without this the Canvas does not draw anything, it draws only the first time.
   'Dim Can As B4XCanvas
   'Can.Initialize(PanelMain)
   Can.ClearRect(Can.TargetRect)
   Can.DrawCircle(PanelMain.Width/2, PanelMain.Height/2,Rnd(50,200)*1dip,xui.Color_Red,True,1dip)
   Can.Invalidate
End Sub
As I wrote, I don't try to find a solution for erase old draw. I found the solution, RemoveAllView.

I'm looking for an explanation.
 
Last edited:
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Thanks I had not read :p
Initialize (View As B4XView)
Initializes the canvas.
In B4A and B4i the canvas will draw on the passed view.
In B4J the canvas which is a view by itself is added to the passed pane as the first element.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
The canvas does not give any results, the image remains the previous one.
Almost as if the image generated previously from the canvas was like a second panel hooked on.
If I release everything (with RemoveAllView), the effect of redrawing can be observed, otherwise it remains the same image
It looks like
B4X:
Can.Initialize(PanelMain)
Adds the canvas in the back of all canvases (even though the documentation says this should add it as the first element). Therefore if a big circle is drawn, the smaller ones will not show up (they are behind the big circle).
This shows the effect
B4X:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private PanelMain As B4XView
   Dim xui As XUI
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   MainForm.Show
   Dim x As Int
   'Output should be ever larger growing circles of different colors
   For x = 0 To 8
       Log(x)
       Sleep(1000)
       Draw(x)
   Next
   PanelMain.RemoveAllViews
   'Output should just be one large red circle
   For x = 8 To 0 Step -1
       Log(x)
       Sleep(1000)
       Draw(x)
   Next
   
End Sub

Private Sub Draw(pick As Int)
   Dim index As Int = pick Mod 9
   Dim listColors(9) As Int = Array As Int (xui.Color_Black,xui.Color_Blue,xui.Color_Cyan,xui.Color_DarkGray,xui.Color_Gray,xui.Color_Green,xui.Color_LightGray,xui.Color_Magenta,xui.Color_Red)
   'PanelMain.RemoveAllViews ' Without this the Canvas does not draw anything, it draws only the first time.
   Dim aCanvas As B4XCanvas
   aCanvas.Initialize(PanelMain)
   aCanvas.DrawCircle(PanelMain.Width/2, PanelMain.Height/2,(50+25*index)*1dip,listColors(index),True,1dip)
   aCanvas.Invalidate
End Sub
I've not found a way (due to lack of knowledge) to bring the canvas up front.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
It looks like
B4X:
Can.Initialize(PanelMain)
Adds the canvas in the back of all canvases (even though the documentation says this should add it as the first element). Therefore if a big circle is drawn, the smaller ones will not show up (they are behind the big circle).
This shows the effect
B4X:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private PanelMain As B4XView
   Dim xui As XUI
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   MainForm.Show
   Dim x As Int
   'Output should be ever larger growing circles of different colors
   For x = 0 To 8
       Log(x)
       Sleep(1000)
       Draw(x)
   Next
   PanelMain.RemoveAllViews
   'Output should just be one large red circle
   For x = 8 To 0 Step -1
       Log(x)
       Sleep(1000)
       Draw(x)
   Next
 
End Sub

Private Sub Draw(pick As Int)
   Dim index As Int = pick Mod 9
   Dim listColors(9) As Int = Array As Int (xui.Color_Black,xui.Color_Blue,xui.Color_Cyan,xui.Color_DarkGray,xui.Color_Gray,xui.Color_Green,xui.Color_LightGray,xui.Color_Magenta,xui.Color_Red)
   'PanelMain.RemoveAllViews ' Without this the Canvas does not draw anything, it draws only the first time.
   Dim aCanvas As B4XCanvas
   aCanvas.Initialize(PanelMain)
   aCanvas.DrawCircle(PanelMain.Width/2, PanelMain.Height/2,(50+25*index)*1dip,listColors(index),True,1dip)
   aCanvas.Invalidate
End Sub
I've not found a way (due to lack of knowledge) to bring the canvas up front.
Erel answered my question: With b4j B4Xcanvas adds a panel. My question is satisfied ;)


Initialize (View As B4XView)
Initializes the canvas.
In B4A and B4i the canvas will draw on the passed view.
In B4J the canvas which is a view by itself is added to the passed pane as the first element.
 
Upvote 0
Top