B4J Question Initialize Widget to call function in another Module

brianoh

Member
Licensed User
Longtime User
As part of trying B4J I've created a separate module to handle the creation of the JavaFx widgets using code. I haven't been able to find how to initialize these widgets to call a function in the Main Module (ie. initialize eg. Button), but only to call a function in the module in which they are created. To overcome that, the action function in the module that creates the widgets simply calls the function in the Main Module to handle the action. Obviously I've done it this way to separate the GUI creation from the main logic. It's no big deal having to handle it this way (in this case) because there is one function to handle many widgets. I would just like to know if there is a way to call the action function in the Main Module directly from the widget rather than create a function in the GUI creation module to do it. There could be situations where this could become less elegant.
 

Daestrum

Expert
Licensed User
Longtime User
If the button in the 'widget' class is public you can call the 'button' initialize from the main module

Widget class
B4X:
Dim b as button
...
'set up the ui etc

Main class
B4X:
dim w as widget
....
w.b.Initialize("widgetButton")
...

Sub widgetButton_Action
' handle the Action event for the button in the widget here
End Sub
 
Upvote 0

brianoh

Member
Licensed User
Longtime User
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Maybe I misunderstood what you are trying to do.
Could you post a tiny example of the application, as it would be easier to see how the parts currently interact.

#Afterthought

If when you initialize the 'widget' in the main class you store a reference to the main class
B4X:
Dim w as widget
...
w.Initialize(Me)
...
and in the widget
B4X:
private parent as object
...
Sub Initialize(pa as Object)
       parent = pa
...
You can then use callsub in widget class to call the routines in the main class
B4X:
' assuming the button action is called but_Action
Sub but_Action
       Dim tmpb As Button = Sender
       CallSub(parent,tmpb.Text)
End Sub
and it will use the text of the button to call the routine in the main class
 
Last edited:
Upvote 0

brianoh

Member
Licensed User
Longtime User
What I would like to be able to do is to initialize the Gui widgets so as to run the Action function in the Main module that is associated with that widget.

What I am having to do is initialize the widget in the Gui-creation module with a function in that module which then calls the function in the main module.

This is in order that I can separate the Gui creation from the main program logic. While this example does not create much additional code, it could in other cases create more code.

A simplified example is as follows:

B4X:
' Main
#Region  Project Attributes
   #MainFormWidth: 250
   #MainFormHeight: 250
#End Region

Sub Process_Globals
   Private fx As JFX
   Public MainForm As Form
   Public c_txf_Display As TextField
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   
   MainForm = Form1
   CreateGui.fn_CreateGui
End Sub

Sub fn_BtnAction(sT_btnText As String)
   
   c_txf_Display.Text = sT_btnText
End Sub

B4X:
'Static code module "CreateGui"
Sub Process_Globals
   Private fx As JFX
End Sub

Sub fn_CreateGui
   
   Main.MainForm.SetFormStyle("UNIFIED")
   Main.c_txf_Display.initialize("")
   Main.MainForm.RootPane.AddNode(Main.c_txf_Display, 50, 20, 50, 33)
   
   Dim const aRsT_Symbols() As String = Array As String("1", "2", "3")
   
   For iN_Pos = 0 To aRsT_Symbols.length -1
     
     Dim btnX As Button
     btnX.Initialize("fn_Btn")
     btnX.Text = aRsT_Symbols(iN_Pos)
     
     Main.MainForm.RootPane.AddNode(btnX, 50 +(iN_Pos * 40), 75, 40, 40)
   Next
   
   Main.MainForm.Show
End Sub

Sub fn_Btn_Action
   
   Dim btnX As Button = Sender
   Main.fn_BtnAction(btnX.Text)
End Sub
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Slightly modified your code
B4X:
' Main
#Region  Project Attributes
   #MainFormWidth: 250
   #MainFormHeight: 250
#End Region

Sub Process_Globals
   Private fx As JFX
   Public MainForm As Form
   Public c_txf_Display As TextField
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   CreateGui.fn_CreateGui(Me) ' pass reference to this class
End Sub

' button 1 will display "one" in textfield etc
Sub fn_1
    c_txf_Display.Text = "one"
End Sub

Sub fn_2
    c_txf_Display.Text = "two"
End Sub

Sub fn_3
    c_txf_Display.Text = "three"
End Sub

B4X:
'Static code module "CreateGui"
Sub Process_Globals
   Private fx As JFX
   Private parent As Object
End Sub

Sub fn_CreateGui(pa As Object)
   parent = pa ' save the reference
   Main.MainForm.SetFormStyle("UNIFIED")
   Main.c_txf_Display.initialize("")
   Main.MainForm.RootPane.AddNode(Main.c_txf_Display, 50, 20, 50, 33)
   
   Dim const aRsT_Symbols() As String = Array As String("1", "2", "3")
   
   For iN_Pos = 0 To aRsT_Symbols.length -1
     
     Dim btnX As Button
     btnX.Initialize("fn_Btn")
     btnX.Text = aRsT_Symbols(iN_Pos)
     
     Main.MainForm.RootPane.AddNode(btnX, 50 +(iN_Pos * 40), 75, 40, 40)
   Next
   
   Main.MainForm.Show
End Sub

Sub fn_Btn_Action
   Dim btnX As Button = Sender
   CallSub(parent,"fn_"&btnX.Text) ' use reference to call routine in Main
End Sub
 
Upvote 0

brianoh

Member
Licensed User
Longtime User
Thanks, it's interesting to know that information. What I would like is to be able to initialize a component to call a function in another module and it appears that cannot be done. I may put in a feature request when I have had more experience with B4J.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…