java - JMenuItem and JMenu used outside of a JMenu component - JMenu sub-menu not working -
i attempting create custom popup menu.
hard requirements following: 1) speech bubble shape 2) transparency 3) menu open until closed via close button
i have managed achieve 3 of above, when attempt add normal sub-menu, won't work. renders if sub menu, not seem register mouse interaction. tried adding actionlistener menu directly, had no effect.
** edit ** adding new sample based on feedback lack of layout , color not applicable problem trying solve, original sample follows new one
import java.awt.color; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.geom.roundrectangle2d; import javax.swing.boxlayout; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.jmenu; import javax.swing.jmenuitem; import javax.swing.jseparator; public class custommenu extends jframe { public custommenu() { super(); setundecorated(true); setalwaysontop(true); setopacity(0.75f); setsize(100, 110); setlocation(800, 600); setshape(new roundrectangle2d.float(0, 0, 100, 110, 25, 25)); getcontentpane().setlayout(new boxlayout(getcontentpane(), boxlayout.y_axis)); setbackground(color.black); jbutton closebutton = new jbutton(); closebutton.setsize(16, 16); closebutton.addactionlistener(new actionlistener() { @override public void actionperformed(actionevent e) { custommenu.this.dispose(); } }); closebutton.setlocation(75, 5); getcontentpane().add(closebutton); jlabel label = new jlabel("menu title"); label.setsize(90, 25); getcontentpane().add(label); jseparator separator = new jseparator(jseparator.horizontal); separator.setsize(90,5); getcontentpane().add(separator); jmenu menu = new jmenu("sub menu"); jmenuitem menuitem = new jmenuitem("sub menu item one"); menuitem.setsize(100, 25); menu.add(menuitem); menuitem = new jmenuitem("sub menu item two"); menuitem.setsize(100, 25); menu.add(menuitem); menu.setsize(100, 25); getcontentpane().add(menu); menuitem = new jmenuitem("menu item one"); menuitem.setsize(100, 25); getcontentpane().add(menuitem); menuitem = new jmenuitem("menu item two"); menuitem.setsize(100, 25); getcontentpane().add(menuitem); menuitem = new jmenuitem("menu item three"); menuitem.setsize(100, 25); getcontentpane().add(menuitem); } public static void main(string args[]) { java.awt.eventqueue.invokelater(new runnable() { @override public void run() { new custommenu().setvisible(true); } }); } } simplest self contained example come below. in advance assistance.
import java.awt.color; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.geom.roundrectangle2d; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.jmenu; import javax.swing.jmenuitem; import javax.swing.jseparator; public class custommenu extends jframe { public custommenu() { super(); setundecorated(true); setalwaysontop(true); setopacity(0.75f); setsize(100, 110); setlocation(800, 600); setshape(new roundrectangle2d.float(0, 0, 100, 110, 25, 25)); setlayout(null); setbackground(color.black); jbutton closebutton = new jbutton(); closebutton.setsize(16, 16); closebutton.addactionlistener(new actionlistener() { @override public void actionperformed(actionevent e) { custommenu.this.dispose(); } }); closebutton.setlocation(75, 5); add(closebutton); jlabel label = new jlabel("menu title"); int y = 0; label.setlocation(10, y); label.setsize(90, 25); add(label); y += label.getheight(); jseparator separator = new jseparator(jseparator.horizontal); separator.setsize(90,5); separator.setlocation(5, y); add(separator); y += separator.getheight(); jmenu menu = new jmenu("sub menu"); jmenuitem menuitem = new jmenuitem("sub menu item one"); menuitem.setbackground(new color(0,0,0,0)); menuitem.setsize(100, 25); menuitem.setlocation(0,0); menu.add(menuitem); menuitem = new jmenuitem("sub menu item two"); menuitem.setbackground(new color(0,0,0,0)); menuitem.setsize(100, 25); menuitem.setlocation(0,25); menu.add(menuitem); menu.setbackground(new color(0,0,0,0)); menu.setsize(100, 25); menu.setlocation(-1, y); add(menu); y += menu.getheight(); menuitem = new jmenuitem("menu item one"); menuitem.setbackground(new color(0,0,0,0)); menuitem.setsize(100, 25); menuitem.setlocation(-1, y); add(menuitem); y += menuitem.getheight(); menuitem = new jmenuitem("menu item two"); menuitem.setbackground(new color(0,0,0,0)); menuitem.setsize(100, 25); menuitem.setlocation(-1, y); add(menuitem); y += menuitem.getheight(); menuitem = new jmenuitem("menu item three"); menuitem.setbackground(new color(0,0,0,0)); menuitem.setsize(100, 25); menuitem.setlocation(-1, y); add(menuitem); } public static void main(string args[]) { java.awt.eventqueue.invokelater(new runnable() { @override public void run() { new custommenu().setvisible(true); } }); } }
#problems...
- null layout
- negative layout position
- alpha based background color
swing doesn't negative positions components
swing can't render alpha based background colors, knows how render opaque , transparent components. using alpha based color prevent swing updating area beneath componet, leads weird paint artefacts , other issues
solutions...
- use appropriate layout manager
- see point 1.
- use
setopaque. if need translucent background, you'll need create custom component , overridepaintcomponentmethod , paint background yourself
it should noted, can control popup window sub menus use, these created deep down in bowels of api (i think maybe via static method, it's been while since dug deep)
Comments
Post a Comment