JDK-6554551 : JMenu Items Won't Render Icons
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_vista
  • CPU: x86
  • Submitted: 2007-05-07
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u4Fixed 7 b15Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows Vista

A DESCRIPTION OF THE PROBLEM :
Enabling system look and feel for Vista causes JMenu items with icons specified (i.e. passing an AbstractAction instance to the JMenu constructor) not to render the icon.

This only occurs in the update to JRE 1.6. The standard 1.6 release doesn't render JMenu items with the improved Vista look and feel, hence the issue doesn't occur.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Define a class extending AbstractAction. Ensure a constructor is specified that accepts a String and Icon. Pass the String and Icon to the super() method.

Create a class that extends JFrame. Create a JMenu instance, passing the AbstractAction extending class. Add this JMenu instance to to a JMenuBar. Add the JMenuBar to the frame.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The icon specified for the JMenu item should render.
ACTUAL -
The icon specified for the JMenu item doesn't render.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*********
TestAction.java
*********/
package com.menutest;

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

public class TestAction extends AbstractAction {
	
	public TestAction(String name, Icon icon) {
		super(name, icon);
	}

	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
	}
}

/***********
MenuTest.java
***********/

package com.menutest;

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

public class MenuTest extends JFrame{

	  public static void main(String [] args)throws Exception{
		    setLookAndFeel();
		    
		    MenuTest menuTest = new MenuTest();
		  }
	
	  public MenuTest() {
	        super("Testing JMenu items with Vista look and feel");
	        
	        JMenuBar menuBar = new JMenuBar();
	        TestAction testAction = new TestAction("Menu1", new ImageIcon(getClass().getResource("Small_Logo.png")));
	        JMenu menuItem = new JMenu(testAction);
	        
	        menuBar.add(menuItem);

	        this.setJMenuBar(menuBar);
	        
	        // Display the JFrame.
	        this.setSize(new Dimension(690, 450));
	        this.setVisible(true);
	        
	        // Adding a listener to detect if the JFrame is closing, to close the application if needed.
	        addWindowListener(new WindowAdapter() {
	            public void windowClosing(WindowEvent e) {
	                System.exit(0);
	            }
	        });
	  }
	  
	  private static void setLookAndFeel() {
		    try {
		      UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		    }
		    catch(Exception e) {
		      System.err.println("Error setting Windows LAF");
		      e.printStackTrace();
		    }
		  }
}
---------- END SOURCE ----------

Comments
EVALUATION On Vista menu icon is painted by checkIcon. However there is a case when checkIcon is not used and because of that menu icon is not painted. This case is top level JMenu. For this case we need to paint icon as before without relying on checkIcon. ---- *** /tmp/geta4761 Mon Jun 4 16:17:37 2007 --- BasicMenuItemUI.java Mon Jun 4 16:15:51 2007 *************** *** 435,445 **** /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); ! if (iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } --- 435,447 ---- /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. + * That is if useCheckAndArrow() is true. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); ! if (! useCheckAndArrow() ! || iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } *************** *** 659,669 **** /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); ! if (iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } --- 661,673 ---- /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. + * That is if useCheckAndArrow() is true. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); ! if (! useCheckAndArrow() ! || iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } ----
04-06-2007