0

Java Swing seems to place the 'Menu Text' after the icon (if present) on MenuItems. See example below.

Window Menu on OSX

It does NOT look very nice.

Is there a way around this?

On OSX the icon fits in the left margin and the text aligns with all other MenuItems.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Lyndon
  • 573
  • 6
  • 24
  • I couldn't understand, there is no image/icon in the said pic of yours, next to the Text. What exactly, am I missing ? Do you want your Minimize and Zoom to come just over, Main Frame, Preferences and Page Setup, is that it ? – nIcE cOw May 08 '12 at 16:57
  • 1
    Do you perhaps have an [SSCCE](http://sscce.org) so I can experiment with it on my Mac at home – Robin May 08 '12 at 16:58
  • @nicE cOw The image for the menu is showing now. The diamond icon means that the window is minimized. The checkmark (tick) icon means that the window has focus. The dot icon means that the window has unsaved changes. That's Apple's convention. Those three icons should be in the left margin of the menu and the texts: Main Frame, Preferences and Page Setup should align (left) with the Minimize and Zoom texts above. – Lyndon May 08 '12 at 17:05
  • @Robin I don't have an SSCCE to hand but all you need is a JFrame with a menu and two MenuItems. One MenuItem with an icon and you will have all you need to demonstrate/test this. I think it's a Swing 'feature' but it's a feature that looks awful... – Lyndon May 08 '12 at 17:09

2 Answers2

2

Do you mean something like this :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JTextPaneExample
{
    private Icon info = UIManager.getIcon("OptionPane.informationIcon");
    private Icon error = UIManager.getIcon("OptionPane.errorIcon");
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("JTextPane Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTextPane tpane = new JTextPane();
        tpane.setContentType("text/html");
        JScrollPane scroller = new JScrollPane();
        scroller.setViewportView(tpane);

        try
        {
            java.net.URL url = new java.net.URL("http://maps.google.es/");
            //tpane.setPage(url);
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }

        frame.setJMenuBar(createMenuBar());

        frame.getContentPane().add(scroller);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    private JMenuBar createMenuBar()
    {
        JMenuBar menuBar = new JMenuBar();
        JMenu windowMenu = new JMenu("Window");
        JMenuItem minimizeItem = new JMenuItem("Minimize");
        minimizeItem.setMargin(new java.awt.Insets(0, 10, 0, 0));
        minimizeItem.setIcon(info);
        minimizeItem.setIconTextGap(1);
        minimizeItem.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        JMenuItem zoomItem = new JMenuItem("Zoom");
        zoomItem.setMargin(new java.awt.Insets(0, 10, 0, 0));
        zoomItem.setIconTextGap(1);
        zoomItem.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem("Check Me", null, true);         
        cbmi.setMargin(new java.awt.Insets(5, 25, 5, 5));
        cbmi.setIconTextGap(17);
        cbmi.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        windowMenu.add(minimizeItem);
        windowMenu.add(zoomItem);
        windowMenu.add(cbmi);
        menuBar.add(windowMenu);
        return menuBar;
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new JTextPaneExample().createAndDisplayGUI();
            }           
        });
    }
}

Here is the Output :

MENUITEM

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • The text does align but you have used a JCheckBoxMenuItem. I need to use a Checkmark, a diamond and a dot. It's interesting that the JCheckBoxMenuItem is actually placed in the left margin just where an icon should be... – Lyndon May 08 '12 at 17:12
  • @Lyndon : Try this new code, I am using Windows, me not on Mac OS, so cann't help you much, might be you can test yourself. Try this new code please :-) – nIcE cOw May 08 '12 at 17:17
  • @Lyndon all Look and Feel has onw API, read API, and if you'll any issue post a SSCCE demonstrating your issue, sure before any your next .... here -1 – mKorbel May 08 '12 at 17:20
  • @mKorbel : Thankyou for pointing me towards this POST, will learn something new today. Just wishing that I could have one MAC too by my side to work on, LOL, but alas I am devoid of one, hehe :-) – nIcE cOw May 08 '12 at 17:24
  • @nicE cOw : I tried your code and on OSX it looks just like a checkmark. That's great but the dot and the diamond is still a problem. Maybe, it is possible to achieve the desired look... Thanks. – Lyndon May 08 '12 at 17:26
  • @nIcE cOw you can to check a posts by (@trashgod), his majesty representing here Swing & Mac OSX knowledges – mKorbel May 08 '12 at 17:26
  • @mKorbel Are you saying trashgod has posted on this? If so, where? – Lyndon May 08 '12 at 17:43
  • @nIcE cOw I'm sure that you'll became in this thread too, but I can't awaiting that default Aqua OSX Look and Feel doesn't supporting basic alingments :-) – mKorbel May 08 '12 at 17:58
  • @mKorbel : Yeah, my knowledge in Mac OS X is nothing, never had the privilege to work on it. Since my first use of computers, I used Windows :-) or somewhere Ubuntu (but again just an amateur in that too) – nIcE cOw May 08 '12 at 18:02
  • If there was a way to change the checkmark in a JCheckBoxMenuItem to a Dot and a Diamond then this may be a work-around. But so far 'It's close but no cigar'... – Lyndon May 08 '12 at 18:05
2

You could try either of these approaches:

  • Unicode characters are appealing, but they offer poor alignment in a variable pitch font:

    JMenuBar menuBar = new JMenuBar();
    JMenu windowMenu = new JMenu("Window");
    windowMenu.add(new JMenuItem("♦ Item"));
    windowMenu.add(new JMenuItem("✓ Item"));
    windowMenu.add(new JMenuItem("• Item"));
    menuBar.add(windowMenu);
    frame.setJMenuBar(menuBar);
    
  • Better, implement the Icon interface, illustrated here and here, using a fixed-size implementation to control geometry. CellTest shows one approach to rendering an arbitrary unicode glyph.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • When it comes to painting, I simply fall back on your answers, they are always full of knowledge :-) – nIcE cOw May 09 '12 at 03:39
  • @trashgod : Thanks for your help. First suggestion does not help really. The alignment of MenuItems text still looks wrong. Second suggestion has problems too as I need a MenuItem for each window in app and each window will have one of several conditions to show (current, minimized, dirty or 'non-active'). I feel that the correct way to do this is create a WindowMenuItem derived from JCheckBoxMenuItem and then add it to the UIManager. Any ideas on this approach would be appreciated. – Lyndon May 09 '12 at 10:51
  • Yes, extending `JMenuItem` is possible, but it's laborious even for a single L&F. The virtue of implementing `Icon` is the leverage over geometry, as shown in updated link above; sorry about the incorrect link earlier. @nIcEcOw's use of `setIconTextGap()` complements the approach. – trashgod May 09 '12 at 15:05