German B4J: customview >> code on the fly

Hallo,
ich verfolge B4X schon seit Jahren. Hatte nur nicht die Zeit mich hier mal einzuarbeiten. Habe nun beim Start von Corona damit begonnen. Hänge aber seitdem eigentlich fest.
Ich würde gerne on the fly code für ein customview erzeugen. Habe X-Beispiele gelesen und probiert. Viele Beispiele sind für B4A. Doku zum 100ersten Male durchgelesen. Ich finde nicht den Fehler den ich mache.
Ich habe mal ein einfaches Beispiel angehangen das nicht funktioniert. Es sollte eigentlich nach dem "Initialize" im customModul das "DesignerCreateView" im customModul aufgerufen werden. Dies passiert einfach nicht. Die BasePane wird dadurch nicht zugeordnet und somit auch nicht das Layout geladen.

Vielleicht kann mir jemand einen kurzen Hinweis geben. Würde gerne dieses geplante Projekt in B4J erstellen.

mfg
Walter

Main:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private ButtonStart As Button
    Private CvM(20) As customModul
    Private i As Int
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("MainView") 'Load the layout file.
    MainForm.Show
    For i = 1 To 3
        CvM(i).Initialize(Me,"CvM_e")
    Next
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ButtonStart_MouseClicked (EventData As MouseEvent)
    For i = 1 To 3
        MainForm.RootPane.AddNode(CvM(i).GetBase,100 * i,100,90,30)
    Next
End Sub
customModul:
Sub Class_Globals
    Private fx As JFX
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private mBase As Pane
    Private ButtonCV As Button
    Private PaneCV As Pane
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
    mBase.Initialize("")
End Sub

Public Sub DesignerCreateView (Base As Pane, Lbl As Label, Props As Map)
    mBase = Base
    Sleep(0)
    mBase.LoadLayout("CVView")
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
    
End Sub

Public Sub GetBase As Pane
    Return mBase
End Sub
 

Attachments

  • customview_CodeOnTheFly.zip
    4.3 KB · Views: 220

klaus

Expert
Licensed User
Longtime User
So wie Du das machen willst geht es nicht.
Du musst, in der Class, eine spezielle Routine erstellen welche die CustomView zur ElternView hinzufügt.
Hast Du schon mal das Kapitel Adding a custom view by code im B4X CustomViews angeschaut?
In diesem Booklet sind auch Beispielprogramme inbegriffen, zum Beispiel xCustomButton.

Die Booklets kannst Du entweder Alle auf einmal runterladen, Alle Sourcecodes sind mit inbegriffen.
Oder Du kannst sie on-line anschauen, dann musst aber die Sourcecodes von der Booklets Haupseite herunterladen.

Noch ein Ratschlag : benutze so oft wie möglich B4XViews, diese benötigen die XUI Library, damit kannst Du cross-platform Views erstellen.
 
Hallo Klaus,
die Beispiele hab ich auch schon übertragen auf meine Aufgabenstellung und ausprobiert. Gleiches Ergebnis.
Sub DesignerCreateView wird nicht aufgerufen. Das customView wird nicht angezeigt.
Wenn ich die Beispiele roh nutze dann funktionieren diese. Aber kein Beispiel nutzt ein LoadLayout im CustomModul. Ist diese in B4J nicht möglich?

Laut Doku "B4X CustomViews" geht das doch wie ich es machen möchte.

Doku:
You can add specific layouts to a CustomView.
Code to load a layout.
Public Sub DesignerCreateView(Base As Object, Lbl As Label, Props As Map)
    mBase = Base 
    Sleep(0)
    mBase.LoadLayout("CustomViewLayout")
End Sub
This code loads the CustomViewLayoutonto mBase.
Note: Sleep(0)before loading the layout.
This is necessary to make sure that the dimensions of mBase are OK.


In den Beispielen ist das CustomView schon mit dem Designer eingefügt. Deswegen wird hier DesignerCreatView aufgerufen. Ich möchte aber mit einer leeren Rootpane starten und hier eine verschiedene Anzahl von CustomViews einfügen.
Ich hab dies schon zB. in .net gemacht. Ist in .net eine Sache auf 5 Minuten. Kann es sein das B4J-CustomViews so schwerer zu verstehen sind?





Main:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private ButtonStart As B4XView
    Private CvM(20) As customModul
    Private i As Int
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("MainView") 'Load the layout file.
    MainForm.Show
'    For i = 1 To 3
'        CvM(i).Initialize(Me,"CvM_e")
'    Next
'    FormUtils.SetMaximized(MainForm,True)
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ButtonStart_MouseClicked (EventData As MouseEvent)
    For i = 1 To 3
        CvM(i).Initialize(Me,"CvM_e")
        CvM(i).AddToParent(MainForm.RootPane, 100 * i,100,90,30)
        'MainForm.RootPane.AddNode(CvM(i).GetBase,100 * i,100,90,30)
    Next
End Sub

Sub ButtonStart_Resize (Width As Double, Height As Double)
    
End Sub



customModul:
Sub Class_Globals
    Private fx As JFX
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private mBase As Pane
'    Private ButtonCV As Button
'    Private PaneCV As Pane
    Private ButtonCV As B4XView
    Private PaneCV As B4XView
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
    mBase.Initialize("")
End Sub

Public Sub DesignerCreateView (Base As Pane, Lbl As Label, Props As Map)
    mBase = Base
    Sleep(0)
    mBase.LoadLayout("CVView")
End Sub

Public Sub AddToParent(Parent As Pane, Left As Int, Top As Int, Width As Int, Height As Int)
    mBase.Initialize("mBase")
    Parent.AddNode(mBase, Left, Top, Width, Height)
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
    
End Sub

Public Sub GetBase As Pane
    Return mBase
End Sub
 
Hallo,
hab zwischenzeitlich weitergeforscht und mir ist es gelungen dass es grundsätzlich mal funktioniert.
Die Beispiele hatten mich auf die "falsche Fährte" geschickt.
So funktioniert es. Auch mit GetBase.

Jetzt kann ich darauf aufbauen.



Main:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private ButtonStart As B4XView
    Private CvM(20) As customModul
    Private i As Int
End Sub

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

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ButtonStart_MouseClicked (EventData As MouseEvent)
    For i = 1 To 3
        CvM(i).Initialize(Me,"CvM_e")
        MainForm.RootPane.AddNode(CvM(i).GetBase,140 * i,100,0,0)
    Next
End Sub

Sub ButtonStart_Resize (Width As Double, Height As Double)
    
End Sub

customModul:
Sub Class_Globals
    Private fx As JFX
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private mBase As Pane
    Private ButtonCV As B4XView
    Private PaneCV As B4XView   
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
    mBase.Initialize("")   
    mBase.LoadLayout("CVView")
End Sub

Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
    
End Sub

public Sub getWidth() As Int
    Return mBase.Width
End Sub

Public Sub getHeight() As Int
    Return mBase.Height
End Sub


Private Sub Base_Resize (Width As Double, Height As Double)
    
End Sub

Public Sub GetBase As Pane
    Return mBase
End Sub
 
Top