Java Swing JMenuBar

I would like to use the JMenuBar from the Java Swing class to do some custom navigation. 3 questions:

Is this possible? (I suspect yes)

Can this be used as a component through the designer or is it built at design time through scripting?

Could someone point me in the right direction.

If you want to look into creating your own component then the Ignition Module SDK is the way to go. You can download everything you need from the current downloads page. The SDK contains some examples/tutorials to get you started and if you have any further questions then feel free to post them in the module developer section of the forum.

Can’t the java swing class be used in jython as described below?

from java.lang import System
from java.awt.event import KeyEvent
from java.awt.event import ActionEvent
from javax.swing import JFrame
from javax.swing import JMenuBar
from javax.swing import JMenuItem
from javax.swing import JMenu
from javax.swing import ImageIcon
from javax.swing import KeyStroke

class Example(JFrame):

def __init__(self):
    super(Example, self).__init__()

    self.initUI()

def initUI(self):

    menubar = JMenuBar()

    iconNew = ImageIcon("new.png")
    iconOpen = ImageIcon("open.png")
    iconSave = ImageIcon("save.png")
    iconExit = ImageIcon("exit.png")

    file = JMenu("File")
    file.setMnemonic(KeyEvent.VK_F)

    imp = JMenu("Import")
    imp.setMnemonic(KeyEvent.VK_M)

    newsf = JMenuItem("Import newsfeed list...")
    bookm = JMenuItem("Import bookmarks...")
    mail = JMenuItem("Import mail...")

    imp.add(newsf)
    imp.add(bookm)
    imp.add(mail)

    fileNew = JMenuItem("New", iconNew)
    fileNew.setMnemonic(KeyEvent.VK_N)

    fileOpen = JMenuItem("Open", iconOpen)
    fileNew.setMnemonic(KeyEvent.VK_O)

    fileSave = JMenuItem("Save", iconSave)
    fileSave.setMnemonic(KeyEvent.VK_S)

    fileExit = JMenuItem("Exit", iconExit,
        actionPerformed=self.onSelect)
    fileExit.setMnemonic(KeyEvent.VK_C)
    fileExit.setToolTipText("Exit application")
    fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
        ActionEvent.CTRL_MASK))

    file.add(fileNew)
    file.add(fileOpen)
    file.add(fileSave)
    file.addSeparator()
    file.add(imp)
    file.addSeparator()
    file.add(fileExit)

    menubar.add(file)

    self.setJMenuBar(menubar)

    self.setTitle("Submenu")
    self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
    self.setSize(320, 220)
    self.setLocationRelativeTo(None)
    self.setVisible(True)

def onSelect(self, e):
    System.exit(0)

Example

Yes, you can use Swing classes in Jython code.

Got it.

Also there are many things that can be embeded into the JMenuBar. This example shows a JButton as well. I beleive that the JComboBox, JTextFeild, etc. can be embeded too.

enjoy.



from javax.swing import JMenuBar
from javax.swing import JMenuItem
from javax.swing import JMenu
from javax.swing import JFrame
from javax.swing import JButton
from javax.swing import ImageIcon
from java.awt import Font

def doHome(event):
    import system
    system.gui.messageBox("Home selected")
def doMenu1(event):
	import system
	system.gui.messageBox("Menu 1 selected")



menubar = JMenuBar()
menubar.background = system.gui.color(0,0,0)
menubar.foreground = system.gui.color(255,255,255)


menu1 = JButton("Home",actionPerformed=doHome)
menu1.background = system.gui.color(0,0,0)
menu1.foreground =  system.gui.color(255,255,255)
menu1.setBorderPainted(False)
menu1.setFont(Font("Ariel", Font.BOLD,12))

menu2 = JMenu("Menu")
menu2.background = system.gui.color(0,0,0)
menu2.foreground =  system.gui.color(255,255,255)

menu3 = JMenu("Reports")
menu3.background = system.gui.color(0,0,0)
menu3.foreground =  system.gui.color(255,255,255)

menu4 = JMenu("Sub Menu")
menu4.background = system.gui.color(0,0,0)
menu4.foreground =  system.gui.color(255,255,255)

menuitem1 = JMenuItem ("Sub Menu 1",actionPerformed=doMenu1)
menuitem1.background = system.gui.color(0,0,0)
menuitem1.foreground =  system.gui.color(255,255,255)

menuitem2 = JMenuItem ("Sub Menu 2")
menuitem2.background = system.gui.color(0,0,0)
menuitem2.foreground =  system.gui.color(255,255,255)

menuitem3 = JMenuItem ("Sub Menu 3a")
menuitem3.background = system.gui.color(0,0,0)
menuitem3.foreground =  system.gui.color(255,255,255)

menuitem3b = JMenuItem ("Sub Menu 3b")
menuitem3b.background = system.gui.color(0,0,0)
menuitem3b.foreground =  system.gui.color(255,255,255)

reportitem1 = JMenuItem ("Report 1")
reportitem1.background = system.gui.color(0,0,0)
reportitem1.foreground =  system.gui.color(255,255,255)

reportitem2 = JMenuItem ("Report 2")
reportitem2.background = system.gui.color(0,0,0)
reportitem2.foreground =  system.gui.color(255,255,255)

reportitem3 = JMenuItem ("Report 3")
reportitem3.background = system.gui.color(0,0,0)
reportitem3.foreground =  system.gui.color(255,255,255)


menu2.add(menuitem1)
menu2.add(menuitem2)
menu4.add(menuitem3)
menu4.add(menuitem3b)
menu2.add(menu4)


menu3.add(reportitem1)
menu3.add(reportitem2)
menu3.add(reportitem3)


menubar.add(menu1)
menubar.add(menu2)
menubar.add(menu3)
menubar.setLocation(100,100)
event.source.parent.parent.parent.setMenuBar(menubar)
menubar.setVisible(1)
	

This was my reason for pointing you towards the Ignition Module SDK. If you want to create a component that you can use throughout the designer just like you would any of the other built in Ignition components then I still think that your best option is to wrap it up in a module.

I never meant to imply that you can't use Java Swing in Jython and I apologize if my answer came off that way.

We got this menu converted to a script module and one of the other guys here at work got the whole thing to be driven from a database table. He has columns for the Ignition roles so that the whole menu system is dynamic based on the role of the person logged in.

The whole thing turned out pretty sweet.

1 Like

Id love to get a look at the final code on this.

1 Like

@djones Hello, I have been dealing with a similar situation and i’m stuck at the moment. maybe you can help,
I’m trying to add a list from my db to create the a popup menu in the Calendar Events, I also added Icons with Colors to the popup so the user can select from the list and it will set and action, and paint the event with the color selected.

i have the following code that works, but what i need is to be able to add names and color to the menu from the client, so have been trying to figure out a way to create from the results in range. but can’t figure it out. the code i have now it’s the following, using a lot from your post(Thank you)

from javax.swing import JMenuItem
from javax.swing import ImageIcon
from com.inductiveautomation.ignition.client.images import PathIcon

def query1(event):
    import system
    system.gui.messageBox("ABD")
def query2(event):
	import system
	system.gui.messageBox("KING Brands")
def query3(event):
	import system
	system.gui.messageBox("Apple & Eve")

def query4(event):
	import system
	system.gui.messageBox("Apple & Eve")
		
iconblue = PathIcon()
iconblue.path = "coloricon/blue.png"
iconred = PathIcon()
iconred.path = "coloricon/red.png"
icongreen = PathIcon()
icongreen.path = "coloricon/green.png"
iconorange = PathIcon()
iconorange.path = "coloricon/orange.png"
menu = system.gui.createPopupMenu([],[])


menuitem1 =  JMenuItem ("ABD",iconblue , actionPerformed=query1)
menu.add(menuitem1)
menu.addSeparator()

menuitem2 =  JMenuItem ("King Brands",iconred,actionPerformed=query2)
menu.add(menuitem2)
menu.addSeparator()

menuitem3 =  JMenuItem ("Apple & Eve ",icongreen,actionPerformed=query3)
menu.add(menuitem3)
menu.addSeparator()

menuitem4 =  JMenuItem ("Libby's",iconorange, actionPerformed=query4)
menu.add(menuitem4)
menu.addSeparator()


menu.setBackground(system.gui.color(0,0,0))

menu.show(event,event.x,event.y)

Goal would be to be able to generate the menu from a (row in range)

What does your reference dataset look like or contain?
If you have a dataset coming in from a query, assuming it has headers like "MenuText","Color","Func"...

from javax.swing import JMenuItem
from javax.swing import ImageIcon
from com.inductiveautomation.ignition.client.images import PathIcon

colorDict = {}
for color in ["blue","red","green","orange"]:
	pi = PathIcon()
	pi.path = "coloricon/%s.png"%color
	colorDict[color] = pi
	
def query1(event):
    import system
    system.gui.messageBox("ABD")
def query2(event):
	import system
	system.gui.messageBox("KING Brands")
def query3(event):
	import system
	system.gui.messageBox("Apple & Eve")

def query4(event):
	import system
	system.gui.messageBox("Apple & Eve")	
scriptDict = {"script1":query1,"script2":query2,"script3":query3,"script4":query4}

menu = system.gui.createPopupMenu()
pyDataSet = system.db.runNamedQuery("My Query")
for row in pyDataSet:
	menuitem =  JMenuItem (row["MenuText"],colorDict[row["Color"]], actionPerformed=scriptDict[row["Func"]])
	menu.add(menuitem)
	menu.addSeparator()
menu.show()

1 Like

thanks but i do not have only 4 colors, or 4 names, or four functions, that i can do easy. the problem is a dynamic menu, which can have 1 , 10, 15, 12, 20, 40, etc number of results, which end up in X number of colors, names, and function. this is where i’m running into the problem.

You could extend JMenuItem and construct the instances with the information needed instead of defining each function individually. But consider limiting the quantity of these items--you'll have trouble if your menu exceeds the vertical space available.

My query is as you describe.

SELECT MenuText, Color, Func from ColorCalendar

Thanks for the time taken, unfortunately, I can’t get it to work, it is obvious I’m not advance enough to do this from a query in the DB , yet, but hopefully very soon. thanks anyway.

Generating menu items with different text, color, and icons is a fairly simple task, although it has some gotchas as mentioned by @pturmel. But generating dynamic functions is another thing all together. Can it be done? Yes it can be, but it is likely to be very error prone as well as opening you’re system up to SQL injection. It isn’t something I would play around with lightly.

I was actually just able to do it, the only thing missing now, it’s to identify which item I’m selecting from the menu. so i can run an update query based on the selecting. thanks everybody for all the help.

That's the crux of the problem, and why I proposed you extend JMenuItem. The menu items themselves need to contain your data reference somehow. A constructor can tuck away arbitrary data in instance properties for later use.

Thanks for all the input, I got it to work in a different way, as I don’t know how to extend the JMenuItem.

so what I did was to create a custom property named “colorind”, I set this property when the user selects from the menu to the event. this gives me a huge string which I then got a substring getting the text, from this text, I then run a select query for color in my db where MenuText= text, and then I update the db with that color. I know this is not the correct way to do it but it works, once I have time to learn how to extend JMenuItem i will change this script.

a link to view my results

via GIPHY