Search code examples
javaswinglook-and-feeljcheckboxnimbus

Missing check square (JCheckBoxMenuItem) while using Nimbus java look and feel


I changed to Nimbus look and feel, as it is described here.

It works fine except for JCheckBoxMenuItems, where the check squares disappeared. The selection color is incorrect too.

This is the code of the popupmenu with the JCheckBoxMenuItems:

public class FilterByNodeUI 
{
    private JPopupMenu filterMenu;
    private PopupMenuButton menu;
    private JMenu eventLogFilters, commandFilters;
    private JCheckBoxMenuItem[] commandsPeriodicalItems, commandsPeriodicalAllPortsItems;
    private JCheckBoxMenuItem alarm, connection, standard;
    private String id;

public FilterByNodeUI(Node node)
{
    this.id = node.getIp();

    filterMenu = new JPopupMenu();
    eventLogFilter();

    int cpNbr = node.getCommands().getCommandsPeriodical().size();
    int cpapNbr = node.getCommands().getCommandsPeriodicalAllPorts().size();
    commandsPeriodicalItems = new JCheckBoxMenuItem[cpNbr];
    commandsPeriodicalAllPortsItems = new JCheckBoxMenuItem[cpapNbr];

    commandFilters = new JMenu("Commands");

    for(int i = 0; i < cpNbr; i++)
    {
        commandsPeriodicalItems[i] = menuItemFactory(node.getCommands().getCommandsPeriodical().get(i).getCommand());
        commandFilters.add(commandsPeriodicalItems[i]);
    }

    commandFilters.addSeparator();

    for(int i = 0; i < cpapNbr; i++)
    {
        commandsPeriodicalAllPortsItems[i] = menuItemFactory(node.getCommands().getCommandsPeriodicalAllPorts().get(i).getCommand());
        commandFilters.add(commandsPeriodicalAllPortsItems[i]);
    }

    filterMenu.add(eventLogFilters);
    filterMenu.add(commandFilters);

    menu = new PopupMenuButton(node.getDispName(), filterMenu);


    commandFilterListeners(commandsPeriodicalItems, node, true);
    commandFilterListeners(commandsPeriodicalAllPortsItems, node, false);   
}

private void eventLogFilter()
{
    alarm = menuItemFactory("Alarm messages");
    standard = menuItemFactory("Standard messages");
    connection = menuItemFactory("Connection messages");

    eventLogFilters = new JMenu("Event Log Messages");
    eventLogFilters.add(alarm);
    eventLogFilters.add(connection);
    eventLogFilters.add(standard);
}

private JCheckBoxMenuItem menuItemFactory(String name)
{
    JCheckBoxMenuItem tmp;
    tmp = new JCheckBoxMenuItem(name);
    tmp.setSelected(true);
    tmp.setUI(new StayOpenCheckBoxMenuItemUI());  // I set a new UI here
    return tmp;
}
}

This is what it looks like now:

missing check square

It seems to me that the new look and feel did not apply for the JCheckBoxMenuitems or the JMenu.

The cause of the problem is that I set a new UI for hte JCheckBoxMenuItems because I do not want to close the popup menu when the user checks/unchecks an item.

Here is the code:

public class StayOpenCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI 
{
   @Override
   protected void doClick(MenuSelectionManager msm) 
   {
       menuItem.doClick(0);
   }

   public static ComponentUI createUI(JComponent c)
   {
       return new StayOpenCheckBoxMenuItemUI();
   }
}

Is there a way to keep this unclosing feature beside the nimbus look and feel?


Solution

  • not an answer code by aterai from OTN

    enter image description here enter image description here

    import java.awt.*;
    import javax.swing.*;
    // JDK 1.6
    //import com.sun.java.swing.*;
    //import com.sun.java.swing.plaf.nimbus.*;
    //__________________________________________
    // JDK 1.7
    import javax.swing.plaf.nimbus.*;
    
    class NimbusCheckIconTest {
    
        public JMenuBar createMenuBar() {
            JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem("checkIcon test");
            UIDefaults d = new UIDefaults();
            d.put("CheckBoxMenuItem[Enabled].checkIconPainter",
                    new MyCheckBoxMenuItemPainter(
                    MyCheckBoxMenuItemPainter.CHECKICON_ENABLED));
            d.put("CheckBoxMenuItem[MouseOver].checkIconPainter",
                    new MyCheckBoxMenuItemPainter(
                    MyCheckBoxMenuItemPainter.CHECKICON_MOUSEOVER));
            d.put("CheckBoxMenuItem[Enabled+Selected].checkIconPainter",
                    new MyCheckBoxMenuItemPainter(
                    MyCheckBoxMenuItemPainter.CHECKICON_ENABLED_SELECTED));
            d.put("CheckBoxMenuItem[MouseOver+Selected].checkIconPainter",
                    new MyCheckBoxMenuItemPainter(
                    MyCheckBoxMenuItemPainter.CHECKICON_SELECTED_MOUSEOVER));
            cbmi.putClientProperty("Nimbus.Overrides", d);
            cbmi.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
            JMenuBar menuBar = new JMenuBar();
            JMenu menu = new JMenu("A Menu");
            menuBar.add(menu);
            menu.add(new JCheckBoxMenuItem("default"));
            menu.add(cbmi);
            menuBar.add(menu);
            return menuBar;
        }
    
        public Container createContentPane() {
            JPanel contentPane = new JPanel(new BorderLayout());
            contentPane.setOpaque(true);
            contentPane.add(new JScrollPane(new JTextArea()));
            return contentPane;
        }
    
        private static void createAndShowGUI() {
            try {
                for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(laf.getName())) {
                        UIManager.setLookAndFeel(laf.getClassName());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            NimbusCheckIconTest demo = new NimbusCheckIconTest();
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setJMenuBar(demo.createMenuBar());
            f.setContentPane(demo.createContentPane());
            f.setSize(320, 240);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }
    //copy: CheckBoxMenuItemPainter.java
    class MyCheckBoxMenuItemPainter extends AbstractRegionPainter {
    
        static final int CHECKICON_ENABLED_SELECTED = 6;
        static final int CHECKICON_SELECTED_MOUSEOVER = 7;
        static final int CHECKICON_ENABLED = 8;
        static final int CHECKICON_MOUSEOVER = 9;
        private int state;
        private PaintContext ctx;
    
        public MyCheckBoxMenuItemPainter(int state) {
            super();
            this.state = state;
            this.ctx = new AbstractRegionPainter.PaintContext(
                    new Insets(5, 5, 5, 5), new Dimension(9, 10), false, null, 1.0, 1.0);
        }
    
        @Override
        protected void doPaint(Graphics2D g, JComponent c,
                int width, int height, Object[] eckey) {
            switch (state) {
                case CHECKICON_ENABLED:
                    paintcheckIconEnabled(g);
                    break;
                case CHECKICON_MOUSEOVER:
                    paintcheckIconMouseOver(g);
                    break;
                case CHECKICON_ENABLED_SELECTED:
                    paintcheckIconEnabledAndSelected(g);
                    break;
                case CHECKICON_SELECTED_MOUSEOVER:
                    paintcheckIconSelectedAndMouseOver(g);
                    break;
            }
        }
    
        @Override
        protected PaintContext getPaintContext() {
            return ctx;
        }
    
        private void paintcheckIconEnabled(Graphics2D g) {
            g.setPaint(Color.GREEN);
            g.drawOval(0, 0, 10, 10);
        }
    
        private void paintcheckIconMouseOver(Graphics2D g) {
            g.setPaint(Color.PINK);
            g.drawOval(0, 0, 10, 10);
        }
    
        private void paintcheckIconEnabledAndSelected(Graphics2D g) {
            g.setPaint(Color.ORANGE);
            g.fillOval(0, 0, 10, 10);
        }
    
        private void paintcheckIconSelectedAndMouseOver(Graphics2D g) {
            g.setPaint(Color.CYAN);
            g.fillOval(0, 0, 10, 10);
        }
    }