Ciao a tutti mi è venuta la voglia di implementare una serie di bottoni con popup allora ho esteso la classe JToggleButton
codice:
public class ButtonPopup extends JToggleButton{
    private JPopupMenu PopupMenu;
    private boolean show = false;
    
    public ButtonPopup(String Text){
        this(Text,null,null);
    }
    public ButtonPopup(String Text, String Tooltip, Icon ico){
        super();
        setBorderPainted(false);
        setFocusable(false);
        if(ico!=null) this.setIcon(ico);
        if(Tooltip!=null && !Tooltip.equals("")) this.setToolTipText(Tooltip);
        if(Text!=null && !Text.equals("")) this.setText(Text);
        PopupMenu = new JPopupMenu();
        this.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent ie) {
                if(show){
                    if(ie.getStateChange()==ItemEvent.SELECTED){
                        JToggleButton B = (JToggleButton)ie.getSource();
                        Rectangle a = B.getBounds();
                        PopupMenu.show(B,0,a.height);
                    }
                    else
                        PopupMenu.setVisible(false);
                }
            };
        });
        PopupMenu.addPopupMenuListener(new PopupMenuListener() {
            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                deselect();
            }
            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                deselect();
            }
            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            }
        });
    }
    private void deselect() {
        this.setSelected(false);
    }
    public void addItemMenu(Component a){
        PopupMenu.add(a);
        show = true;
    }
    public void deleteItemMenu(int i){
        PopupMenu.remove(i);
        if(PopupMenu.getComponentCount()==0)
            show = false;
    }
    
}
e ho scritto il mio codice personalizzato che va più che bene
codice:
private void populateToolbar(){
        ButtonPopup Views = new ButtonPopup("", "Views", new ImageIcon("icons\\decks\\views.png"));
            JMenuItem Views_top = new JMenuItem("Top"); Views.addItemMenu(Views_top);
            JMenuItem Views_front = new JMenuItem("Front"); Views.addItemMenu(Views_front);
            JMenuItem Views_left = new JMenuItem("Left"); Views.addItemMenu(Views_left);
        ButtonPopup Decks = new ButtonPopup("", "Decks", new ImageIcon("icons\\decks\\decks.png"));    
            JMenuItem Decks_add = new JMenuItem("Add"); Decks.addItemMenu(Decks_add);
            Decks_add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                s.setAction(s.ADD_DECK);
            }
        });
            JMenuItem Decks_delete = new JMenuItem("Delete"); Decks.addItemMenu(Decks_delete);
        ButtonPopup Bulkheads = new ButtonPopup("", "Decks", new ImageIcon("icons\\decks\\bulkheads.png"));        
            JMenuItem Bulkheads_add = new JMenuItem("Add"); Bulkheads.addItemMenu(Bulkheads_add);
            JMenuItem Bulkheads_delete = new JMenuItem("Delete"); Bulkheads.addItemMenu(Bulkheads_delete);
        ToolBar.add(Views);
        ToolBar.add(Decks);
        ToolBar.add(Bulkheads);
}
Ma ci sono due problemi: intanto quando clicco su un'altro bottone ed un popup è aperto il click serve per chiuderlo e solo con un'altro click si può aprire il menu (poco grave)
Il secondo è che quando clicco su una voce di menu mi ritrovo la seguente eccezione
codice:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at javax.swing.JPopupMenu.setVisible(JPopupMenu.java:737)
	at javax.swing.JPopupMenu.menuSelectionChanged(JPopupMenu.java:1421)
	at javax.swing.MenuSelectionManager.setSelectedPath(MenuSelectionManager.java:94)
	at javax.swing.MenuSelectionManager.clearSelectedPath(MenuSelectionManager.java:126)
	at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:808)
	at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:850)
	at java.awt.Component.processMouseEvent(Component.java:6290)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6055)
	at java.awt.Container.processEvent(Container.java:2039)
	at java.awt.Component.dispatchEventImpl(Component.java:4653)
	at java.awt.Container.dispatchEventImpl(Container.java:2097)
	at java.awt.Component.dispatchEvent(Component.java:4481)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4575)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4236)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4166)
	at java.awt.Container.dispatchEventImpl(Container.java:2083)
	at java.awt.Window.dispatchEventImpl(Window.java:2482)
	at java.awt.Component.dispatchEvent(Component.java:4481)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:648)
	at java.awt.EventQueue.access$000(EventQueue.java:84)
	at java.awt.EventQueue$1.run(EventQueue.java:607)
	at java.awt.EventQueue$1.run(EventQueue.java:605)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
	at java.awt.EventQueue$2.run(EventQueue.java:621)
	at java.awt.EventQueue$2.run(EventQueue.java:619)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:618)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Come risolvere?