B4J Question How to add Node.Id to a view using the Designer?

Diceman

Active Member
Licensed User
1) I noticed when traversing through the nodes on a form the node has an Id property. But I don't see any way to add that using the Designer. I thought there should be an Id property for the node in the properties pane in the Designer.

2) Is the Node.Id available in B4A and B4i?

I'm using B4J v8.80.

TIA
 

Diceman

Active Member
Licensed User
Use the Tag property instead. It is available in the three platforms and can be set with the designer.

Ok, thanks. I was looking at the "XUI View Example - B4J" and when I traversed the nodes, some of the nodes already had values in some of the node.id and node.tag properties that were not put there in code or the designer (see below). I wondered how they got there and I wasn't sure if node.id could be useful for the programmer. If the id property is only in B4J then I will have to use the Tag property instead.

Where did these values come from?
B4X:
   i=0
   ListOfButtons.Initialize
   For Each v As Node In MainForm.RootPane.GetAllViewsRecursive
         i=i+1
        Log($"(${i}) node.id="${v.Id}" node.Tag="${v.Tag}""$)
        If v.Id = "Btn" And v Is Button Then
          ListOfButtons.Add(v)
        End If
   Next
   Dim ii As Int = 0
   For Each b As Button In ListOfButtons
     b.Text = "Num " & ii
     ii = ii + 1
   Next

'Log (with values in Id and Tag that I can't explain):

(3) node.id="arrow-button" node.Tag=""
(4) node.id="arrow" node.Tag=""
(5) node.id="list-view" node.Tag=""
(6) node.id="virtual-flow" node.Tag=""
(92) node.id="" node.Tag="clear"
(94) node.id="" node.Tag="v"
(104) node.id="" node.Tag="reveal"
(106) node.id="" node.Tag="v"

Is there any way to reference in code the View's Name (or Node's name) that is defined in the Designer without having to duplicate it in the Tag property? Most languages allow finding the view/control via its name. I find it redundant to have it in 2 locations (Name & Tag) because updating the view name means updating the tag as well.

TIA
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Views don't have names. Views are regular objects and objects don't have names. You can also load the same layout multiple times.
Don't use Node.id.
Avoid adding a counter to a For Each loop.
There are many ways to organize the views.

Tip: use B4XView instead of Node. It is cross platform and in most cases more powerful.

What are you trying to do?
 
Upvote 0

Diceman

Active Member
Licensed User
Views don't have names. Views are regular objects and objects don't have names. You can also load the same layout multiple times.
Don't use Node.id.
Avoid adding a counter to a For Each loop.
There are many ways to organize the views.

Tip: use B4XView instead of Node. It is cross platform and in most cases more powerful.

What are you trying to do?

I'm trying to match up views to columns from an SQLite table without writing the names in code (less coding the better). I wanted to create a Map that contained the SQLite ColumnName as the key and the View or view name as the value. Each view that corresponds to a table column would have the table column name as its tag. In Delphi it is trivial because each TDBEdit field for example, would have a Datasource property (points indirectly to table) and the ColumnName property for the table. All of the column data retrieved from the table row gets automatically put into the proper views when a new row is retrieved, and when the record is saved it retrieves the column values from the views and stores it into the table. There is no need to write custom code for every form.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I would have used the tag property for this and build a map:
B4X:
Root.LoadLayout("layout")
For Each v As B4XView In Root.GetAllViewsRecursive
 If v.Tag <> Null Then
   Dim Tag As String = v.Tag
   If Tag.StartsWith("map_") Then MapOfViews.Put(Tag.Substring(4), v)
 End If
Next

The tag of all views that should be added to this map should start with map_.

B4X:
Sub GetView(Name As String) As B4XView
 Return MapOfViews.Get(Name)
End Sub
 
Upvote 0

Diceman

Active Member
Licensed User
Erel,

I'm obviously doing something wrong because my iteration over Root.GetAllViewsRecursive are returning only 2 views with tags starting with "map" even though every view on the form has such a "map..." tag. I have attached a sample app using your XUI Views Example app. I chose this app because it has a variety of B4XViews in it.

Most of the tags show up as an empty string.


B4X:
Sub BuildViewMap
    Private locMsg As String
    Log("Loading MapOfViews ---->")
    MapOfViews.Initialize
    Private locNdx As Int=0
    For Each v As B4XView In Base.GetAllViewsRecursive
        If v.Tag <> Null Then
            locNdx = locNdx + 1                                                    'Counter is for debugging purposes only
            Dim Tag As String = v.Tag
            If Tag.StartsWith("[") = False Then                    'Ignore internal views with tag "[...]"
                If Tag.StartsWith("map") Then                         'Is this one of our tags?
                    MapOfViews.Put(Tag, v)                                    'Put the whole tag in the map (we don't care about the "map" prefix)
                    locMsg = "*"
                Else
                    locMsg = " "   
                End If
                Log($"${locMsg}Tag(${locNdx})=${Tag}                ${GetType(v)}"$)
            End If
        End If
    Next
    Log("==================")
    Log("MapOfViews: Total Views Loaded=" & (MapOfViews.Size))
    For Each locKey As String In MapOfViews.Keys
        Log(locKey)
    Next
    Log("=== End MapOfViews ===")
End Sub

Sub GetView(Name As String) As B4XView
    BuildViewMap                                                                        'Put here for testing purposes only
    Private locB4XView As B4XView
    locB4XView = MapOfViews.Get(Name)                                'Lets see if we can find the view with tag=Name
    Return locB4XView
End Sub

Private Sub btnExecute_Click
    Private locSearch As String="mapB4XFloatTextField1"    'Look for any tag string
    Private locViewFnd As B4XView
    locViewFnd = GetView(locSearch)                                            'We will look for one of the views using locSearch

    If locViewFnd.IsInitialized Then                                        'Did we find the view with the tag?
        Log("View Found: " & locViewFnd.Tag)
    Else
        Log("View NOT FOUND: " & locSearch)
    End If
End Sub

Here is the log file when it iterates through the views:
B4X:
Waiting for debugger to connect...
Program started.
Index time: 4 ms (139 Items)
Loading MapOfViews ---->
Tag(2)=                javafx.scene.control.ComboBox
Tag(3)=                javafx.scene.layout.StackPane
Tag(4)=                javafx.scene.layout.Region
Tag(5)=                javafx.scene.control.skin.ComboBoxListViewSkin$3
Tag(6)=                javafx.scene.control.skin.VirtualFlow
Tag(7)=                javafx.scene.control.skin.VirtualFlow$ClippedContainer
Tag(8)=                javafx.scene.Group
Tag(9)=                javafx.scene.Group
Tag(10)=                com.sun.javafx.scene.control.VirtualScrollBar
Tag(11)=                javafx.scene.layout.StackPane
Tag(12)=                javafx.scene.control.skin.ScrollBarSkin$2
Tag(13)=                javafx.scene.layout.Region
Tag(14)=                javafx.scene.control.skin.ScrollBarSkin$3
Tag(15)=                javafx.scene.layout.Region
Tag(16)=                javafx.scene.layout.StackPane
Tag(17)=                javafx.scene.control.skin.ScrollBarSkin$1
Tag(18)=                com.sun.javafx.scene.control.VirtualScrollBar
Tag(19)=                javafx.scene.layout.StackPane
Tag(20)=                javafx.scene.control.skin.ScrollBarSkin$2
Tag(21)=                javafx.scene.layout.Region
Tag(22)=                javafx.scene.control.skin.ScrollBarSkin$3
Tag(23)=                javafx.scene.layout.Region
Tag(24)=                javafx.scene.layout.StackPane
Tag(25)=                javafx.scene.control.skin.ScrollBarSkin$1
Tag(26)=                javafx.scene.layout.StackPane
Tag(27)=                javafx.scene.control.skin.ComboBoxListViewSkin$2$1
Tag(28)=                com.sun.javafx.scene.control.LabeledText
Tag(30)=                javafx.scene.image.ImageView
Tag(31)=                javafx.scene.control.Label
Tag(32)=                com.sun.javafx.scene.control.LabeledText
Tag(33)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(34)=                javafx.scene.canvas.Canvas
Tag(35)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(36)=                javafx.scene.canvas.Canvas
Tag(37)=                javafx.scene.control.Label
Tag(38)=                com.sun.javafx.scene.control.LabeledText
Tag(39)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(40)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(41)=                javafx.scene.canvas.Canvas
Tag(42)=                javafx.scene.control.Label
Tag(43)=                com.sun.javafx.scene.control.LabeledText
Tag(44)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(45)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(46)=                javafx.scene.canvas.Canvas
Tag(47)=                javafx.scene.control.Label
Tag(48)=                com.sun.javafx.scene.control.LabeledText
Tag(49)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(50)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(51)=                javafx.scene.canvas.Canvas
Tag(52)=                javafx.scene.control.Label
Tag(53)=                com.sun.javafx.scene.control.LabeledText
Tag(54)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(55)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(56)=                javafx.scene.canvas.Canvas
Tag(57)=                javafx.scene.control.Label
Tag(58)=                com.sun.javafx.scene.control.LabeledText
Tag(59)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(60)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(61)=                javafx.scene.canvas.Canvas
Tag(62)=                javafx.scene.control.Label
Tag(63)=                com.sun.javafx.scene.control.LabeledText
Tag(64)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(65)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(66)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(67)=                javafx.scene.image.ImageView
Tag(68)=                javafx.scene.image.ImageView
Tag(69)=                javafx.scene.image.ImageView
Tag(70)=                javafx.scene.image.ImageView
Tag(71)=                javafx.scene.image.ImageView
Tag(72)=                javafx.scene.image.ImageView
Tag(73)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(74)=                javafx.scene.canvas.Canvas
Tag(75)=                javafx.scene.control.Label
Tag(76)=                com.sun.javafx.scene.control.LabeledText
Tag(77)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(78)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(79)=                javafx.scene.canvas.Canvas
Tag(80)=                javafx.scene.control.Label
Tag(81)=                com.sun.javafx.scene.control.LabeledText
Tag(82)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
*Tag(83)=mapImageView1                javafx.scene.image.ImageView
Tag(84)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(85)=                javafx.scene.control.TextField
Tag(86)=                javafx.scene.layout.Pane
Tag(87)=                javafx.scene.shape.Path
Tag(88)=                javafx.scene.text.Text
Tag(89)=                javafx.scene.Group
Tag(90)=                javafx.scene.shape.Path
Tag(91)=                javafx.scene.image.ImageView
Tag(92)=clear                javafx.scene.control.Label
Tag(93)=                com.sun.javafx.scene.control.LabeledText
Tag(94)=v                javafx.scene.control.Label
Tag(95)=                com.sun.javafx.scene.control.LabeledText
Tag(96)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(97)=                javafx.scene.control.PasswordField
Tag(98)=                javafx.scene.layout.Pane
Tag(99)=                javafx.scene.shape.Path
Tag(100)=                javafx.scene.text.Text
Tag(101)=                javafx.scene.Group
Tag(102)=                javafx.scene.shape.Path
Tag(103)=                javafx.scene.image.ImageView
Tag(104)=reveal                javafx.scene.control.Label
Tag(105)=                com.sun.javafx.scene.control.LabeledText
Tag(106)=v                javafx.scene.control.Label
Tag(107)=                com.sun.javafx.scene.control.LabeledText
Tag(108)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(109)=                javafx.scene.canvas.Canvas
Tag(110)=                javafx.scene.control.Label
Tag(111)=                com.sun.javafx.scene.control.LabeledText
Tag(112)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(113)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(114)=                javafx.scene.canvas.Canvas
Tag(115)=                javafx.scene.control.Label
Tag(116)=                com.sun.javafx.scene.control.LabeledText
Tag(117)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(118)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(119)=                javafx.scene.image.ImageView
Tag(120)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(121)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(122)=                javafx.scene.image.ImageView
Tag(123)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(124)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(125)=                javafx.scene.image.ImageView
Tag(126)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(127)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(128)=                javafx.scene.canvas.Canvas
Tag(129)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(130)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
Tag(131)=                javafx.scene.canvas.Canvas
Tag(132)=                anywheresoftware.b4j.objects.PaneWrapper$ConcretePaneWrapper$NonResizePane
*Tag(133)=mapbtnExecute                javafx.scene.control.Button
Tag(134)=                com.sun.javafx.scene.control.LabeledText
==================
MapOfViews: Total Views Loaded=2
mapImageView1
mapbtnExecute
=== End MapOfViews ===
View NOT FOUND: mapB4XFloatTextField1
 

Attachments

  • GetTags Using XUI Views Example.zip
    9.9 KB · Views: 120
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The case here is more complicated and related to custom views. Read this tutorial: https://www.b4x.com/android/forum/t...om-clv-or-any-other-container.117992/#content
Custom views classes are not views. You will not be able to put all of them in a Map. You will need to treat each type differently.

B4X:
Sub BuildViewMap
    Dim SwiftButtons As Map 'should be a global variable
    SwiftButtons.Initialize
    For Each v As B4XView In Base.GetAllViewsRecursive
        If v.Tag Is SwiftButton Then
            Dim sf As SwiftButton = v.Tag
            'if you like to filter it by the tag then do it here, with sf.Tag
            SwiftButtons.Put(sf.Tag, sf)
        Else if v.Tag Is RoundSlider Then
            '....
        End If
    Next
End Sub
 
Upvote 0
Top