B4J Tutorial Designer Menu Items

Menus in the internal designer are declared as JSON strings.

If you have never worked with the JSON format then it is a good time to learn this format. It is simple and very popular. Short tutorial: http://www.vogella.com/tutorials/JSON/article.html

In our case the JSON string describes a list of menu items. Each menu item can hold other menu items.
Each item can be described as a simple string or as a map.
Simple context menu:
B4X:
["Context Item #1", "Context Item #2", "Context Item #3"]

The result is:

SS-2015-07-26_12.03.05.png



To access all the attributes of each item you need to use the map format.
The following fields are available (note that the field names are case sensitive):

Text - The item's text. This is the only required field. Underscore sets the mnemonic character.
EventName - Sets the sub that will handle the events. If not set then the EventName will be the same as the control's event name property.
Tag - An arbitrary string that will be set as the item's tag.
Enabled - Sets whether the menu item is enabled. This is a boolean value (without quotes).
Children - Holds a list of child menu items.
Selected - Sets whether the menu item is checked or not.
Image - Image file name.

Example:
B4X:
[
   {Text: "_File", Children:
     ["_New", "_Save",
     {Text: "_Export", Children: ["Zip File", "Tar File"]},
     "-",
     "_Close"]
   },
   {Text: "_Edit", Children:[] },
   {Text: "_Help", Children:
     [
       {Text: "Disabled Item", Enabled: False},
       {Text: "Item With Unique Event Name",
         EventName: "mnu1234",
         Image: "EffectNone.png" },
  {Text: "Item With Tag", Tag: "MyTag"}
     ]
   }
]

Result:

SS-2015-07-26_12.18.45.png



Context Menus


SS-2015-07-26_11.58.27.png


MenuBar

SS-2015-07-26_12.10.47.png


Note that the top menus of the MenuBar must have a Children attribute.

Use a simple string item with the value of "-" to create a separator.

Events

The Action event will be raised when a menu item is clicked. By default the event name (sub prefix) will be the same as the parent control event name.
You can get the menu item with code similar to:
B4X:
Sub MenuBar1_Action
   Dim mi As MenuItem = Sender

End Sub
You can get the Tag or Text from the menu item to decide on the required action.

Shortcuts (accelerators)

SS-2015-07-29_10.00.56.png


You can add shortcut keys to menu items. This is done with the Shortcut key. The value is a map with Key and optionally one or more modifiers.

For example to assign F1 as the shortcut:
B4X:
 {Text: "Item1", Shortcut: {Key: "F1"}}
Ctrl + S:
B4X:
{Text: "Item1", Shortcut: {Key: "S", Modifier: "CONTROL"}}
Ctrl + Alt + S:
B4X:
{Text: "Item1", Shortcut: {Key: "S", Modifier: ["CONTROL", "ALT"]}}
The possible modifiers values: ALT, CONTROL, SHIFT and SHORTCUT (Mac button).
 
Last edited:

tdocs2

Well-Known Member
Licensed User
Longtime User
Thank you, Erel.

I must sound like a newbie (and in B4J, I am), but I cannot figure out how to capture the event when "_New" is clicked.

Also, when a map is specified:

B4X:
       {Text: "Item With Unique Event Name",
         EventName: "mnu1234",
         Image: "EffectNone.png" },

do I set up a Sub mnu1234?

Sandy

WISH: A separate Menu Designer for B4J - that matches the simplicity of the Internal Designer. Generates events for all menu items, specifies structure, etc. (All my wishes are BIG WISHES:))

Thank you, Erel - if you truly achieve a B4J, B4A, and B4i unified and transparent environment (or close)... Not a WISH more like a DREAM..
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
In the example above (first post) the EventName is not set. This means that the MenuBar event name will be used. So it should be:
B4X:
Sub MenuBar1_Action

This will handle the events of all the menu items except the ones that explicitly set the event name.

do I set up a Sub mnu1234?
B4X:
Sub mnu1234_Action
 

tdocs2

Well-Known Member
Licensed User
Longtime User
Thank you, Erel.

I am still having problems (newbie, newbie):

B4X:
ub MenuBar1_Action
     Log("Save")
     Dim mi As MenuItem = Sender
    
    
End Sub

How do I capture _Save?

Sandy
 

tdocs2

Well-Known Member
Licensed User
Longtime User
Thank you, Derez.

I will give it a try....

Best regards.

Sandy
 

derez

Expert
Licensed User
Longtime User
How can I change the status of Enabled/Disabled item by code in the application ?
Example: I have two items, Save and Save As. Save should be disabled until a filename is selected using Save As.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can use this code to build a map based on the menu items tag:
B4X:
Private Sub CollectMenuItems(Menus As Map, Items As List)
   For Each mi As MenuItem In Items
     If mi.Tag <> Null And mi.Tag <> "" Then Menus.Put(mi.Tag, mi)
     If mi Is Menu Then
       Dim mn As Menu = mi
       CollectMenuItems(Menus, mn.MenuItems)
     End If
   Next
End Sub
Now you will have simple access to all menu items with tags.
B4X:
Dim menus As  Map 'better to make it a global variable
menus.Initialize
CollectMenuItems(menus, MenuBar1.Menus)
Dim mi As MenuItem = menus.Get("MyTag")
mi.Enabled = False

Edit: added the missing call to CollectMenuItems.
 
Last edited:

derez

Expert
Licensed User
Longtime User
B4X:
Private Sub CollectMenuItems(Menus As Map, Items As List)
How do I create the items list of menuitems ?
 

Hanstel

Member
Licensed User
im completely new to b4j, is "Designer Menu Item" working for web apps too? how about the context menu invoke by right-click?
 

GMan

Well-Known Member
Licensed User
Longtime User
Hoi Erel, i got an error with the example code:

org.json.JSONException: Expected literal value at character 356 of [

The rest is the pasted code from Post one
 

GMan

Well-Known Member
Licensed User
Longtime User
Just deleted the old menubar and inserted a new one - works again.
So maybe the code above has an issue ?
 

Saverio

Member
Licensed User
Longtime User
{Text: "Item1", Shortcut: {Key: "F1"}}
Assign just "F1" key, without any Modifier, will not fire any event, unless handle by code the KeyEvent.
Even setting all the modifiers to "ignore"(ref. KeyCombination: getName) that will set all the modifier state as "ANY".
At least on my pc, win7 - jdk1.8.0_131, with Italian keyboard layout.
As I read on the net, it is an intetional limitation by javafx team.
So I say, why show "F1" as shortcut, in the menuitem, and then do not fire any event?
Can you confirm that?
Thanks
 

Saverio

Member
Licensed User
Longtime User
It works fine here. Just added a MenuBar with the designer and added this code (with the default menu template):
B4X:
Sub MenuBar1_Action
   Log(Sender)
End Sub
Ok, I leave out some detail...sorry :)

Maked just fresh app with a MenuBar and a TextArea.
When the TextArea has the focus, here, isn't work.
A Shortcut should behave system wide or, at least, application wide.
Note: I'm not saying that it is a B4J fault.
 

Attachments

  • Shortcut.zip
    2.2 KB · Views: 831
Top