Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force JPopupMenu to show title even if Look and Feel UI dictates otherwise?

Javadoc for JPopupMenu constructor says the following:

JPopupMenu

public JPopupMenu(String label)

Constructs a JPopupMenu with the specified title.

Parameters:
    label - the string that a UI **may** use to display as a title for the popup menu.

Key word being "may". Evidently in the default UI, such titles are ignored when creating a popup menu. I very much want such titles in some of my popup menus to be used regardless of whether or not the L&F thinks I should. I can't find the hook to make it so. Evidently, this is buried deep in the UI code somewhere. Is there a way to override this default?

Failing that, I have tried adding a disabled menu item as the first item of the menu. Trouble with that is then I lose control of its rendering, and it renders in the "greyed out" style instead of appearing as the important title. If I don't disable it, then it renders as I want, but is selectable, which a title would not be.

So bottom line, how do I either force the UI to display my title, or failing that, how do I add a non-selectable menu item at the top of the menu that I have full rendering control over?

like image 554
Steve Cohen Avatar asked Oct 31 '25 16:10

Steve Cohen


1 Answers

I had similar problem (I mean the original question). I solved it this way:

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;

public class LabeledPopupMenu extends JPopupMenu
{
    private String originalLabelText = null;
    private final JLabel label;

    private static String replaceHTMLEntities(String text)
    {
        if (-1 != text.indexOf("<") ||
            -1 != text.indexOf(">") ||
            -1 != text.indexOf("&"))
        {
            text = text.replaceAll("&", "&amp;");
            text = text.replaceAll("<", "&lt;");
            text = text.replaceAll(">", "&gt;");
        }
        return text;
    }

    public LabeledPopupMenu()
    {
        super();
        this.label = null;
    }

    public LabeledPopupMenu(String label)
    {
        super();
        originalLabelText = label;
        this.label = new JLabel("<html><b>" +
            replaceHTMLEntities(label) + "</b></html>");
        this.label.setHorizontalAlignment(SwingConstants.CENTER);
        add(this.label);
        addSeparator();
    }

    @Override public void setLabel(String text)
    {
        if (null == label) return;
        originalLabelText = text;
        label.setText("<html><b>" +
            replaceHTMLEntities(text) +
            "</b></html>");
    }

    @Override public String getLabel()
    {
        return originalLabelText;
    }
}

I have tested it ony on Mac with default L&F, but it worked for me:

public static void main(String[] args)
{
    JFrame frame = new JFrame();
    frame.setSize(100, 100);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocation(100, 100);
    frame.setVisible(true);

    LabeledPopupMenu myPopup = new LabeledPopupMenu("Say & <something>");
    myPopup.add(new JMenuItem("Sample item"));
    myPopup.show(frame, 50, 50);
}
like image 69
Roman Horváth Avatar answered Nov 03 '25 08:11

Roman Horváth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!