B4J Question Trayicon menu with subitems

ThRuST

Well-Known Member
Licensed User
Longtime User
Is it possible to create submenu items for the popupmenu in a Trayicon menu?
If so, maybe Derez menu designer be used for this? The menu designer can be found here
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
It can be done with JavaObject:
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI 
    Private Button1 As B4XView
    Private ActionListener As Object
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    Dim st As SystemTray
    st.Initialize
    Dim icon As TrayIcon
    icon.Initialize("icon", xui.LoadBitmap(File.DirAssets, "logo.png"), Null)
    st.AddTrayIcon(icon)
    Dim jo As JavaObject = icon
    ActionListener = jo.CreateEventFromUI("java.awt.event.ActionListener", "ActionListener", Null)
    jo.RunMethod("setPopupMenu", Array(CreatePopupMenu))
    
End Sub

Sub ActionListener_Event (MethodName As String, Args() As Object) As Object
    If MethodName = "actionPerformed" Then
        Dim jo As JavaObject = Args(0)
        Dim command As String = jo.RunMethod("getActionCommand", Null)
        Log("Clicked on: " & command)
    End If
    Return Null
End Sub

Sub CreatePopupMenu As JavaObject
    Dim popup As JavaObject
    popup.InitializeNewInstance("java.awt.PopupMenu", Null)
    popup.RunMethod("add", Array(CreateMenuLabel("Item 1")))
    popup.RunMethod("add", Array(CreateMenuWithChildren("Item 2", Array("AAA", "BBB", "CCC"))))
    popup.RunMethod("add", Array(CreateMenuLabel("Item 3")))
    popup.RunMethod("add", Array(CreateMenuLabel("Item 4")))
    Return popup
End Sub

Sub CreateMenuLabel(str As String) As Object
    Dim mi As JavaObject
    mi.InitializeNewInstance("java.awt.MenuItem", Array(str))
    mi.RunMethod("addActionListener", Array(ActionListener))
    Return mi
End Sub

Sub CreateMenuWithChildren(str As String, children As List) As Object
    Dim mi As JavaObject
    mi.InitializeNewInstance("java.awt.Menu", Array(str))
    For Each s As String In children
        mi.RunMethod("add", Array(CreateMenuLabel(s)))
    Next
    Return mi
End Sub

1599715885632.png
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
@Erel Wow, I didn't think this even was possible from the tray. I'll study your solution, this is indeed great work.

Haven't tried it yet but I assume the menu triggers just like the default tray behavior.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
@Erel A doubleclick functionality to this solution would be nice.
??? Can you explain what you are trying to achieve ???
Anyway, a double click is easy enough to detect, just time the timing between clicks, if they're short enough, then consider it a double click
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
I want to add a doubleclick event sub to Erel's solution but I cannot get that to work. It's a default behavior with the tray icon and so I find it useful to show the pane.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
Have you tried logging the Methodism and Args to see if it triggers differently?
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
Yes it seems to work differently than the default trayicon behavior so the eventsub for DoubleClick is not available.
EventData can not be used even though it would be nice if it did when I tried this

B4X:
Sub ActionListener_Event (MethodName As String, Args() As Object, EventData As MouseEvent) As Object
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
How can I detect if the left mouse button is clicked inside the ActionListener event?
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
@Erel How to implement the doubleclick functionality? Cableguy adviced the use of a Timer in the solution.
If left click cannot be detected it seems difficult. Perhaps Roycefer's jAWTRobot library can be a rescue.
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
Like this? What about reading the mouse buttons in sub MouseListener using which parameters?

B4X:
' MouseListener
    ActionListener = jo.CreateEventFromUI("java.awt.event.MouseListener", "MouseListener", Null)
    jo.RunMethod("addMouseListener", Null)
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
Actually I solved it like this

B4X:
' MouseListener
    Dim event As Object = jo.CreateEventFromUI("java.awt.event.MouseListener", "MouseListener", Null)
    jo.RunMethod("addMouseListener", Array(event))

B4X:
Sub MouseListener_Event (MethodName As String, Args() As Object) As Object
   
    Dim MouseEvent As JavaObject = Args(0)
    Dim WhichButton As Int
    WhichButton = MouseEvent.RunMethod("getButton", Null)
    Log (WhichButton)
   
    ' Read left mouse button
    If WhichButton = 1 Then
        MainForm.Show
    End If
   
    Return Null
   
End Sub

And for double click I assume I'll implement Cableguys recommendation to use a timer. I'll be clicking like a pro. Thanks.
Cheers :cool:👌
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
Longtime User
Another issue araised. I want to update the tray popupmenu because I change the names and behavior dynamically. Since I change the variables in the menuitems I need to someway rebuild the menu from scratch, or update it before it is shown. Instead of a static menu I use string variables as menuitems. How can the changes be visible in the tray menu without having to restart the application?
 
Last edited:
Upvote 0

Similar Threads

Top