5

I need to add a label on the right hand side of a JMenuItem, like the labels shown below:

menu items with labels on the right side

I have an application that uses Ctrl++ and Ctrl+- to zoom into an image. However, the + key by default (without Shift) is the = key. When I try adding accelerators for these menu items, the Ctrl+- shortcut label displays as "Ctrl+Minus" (I would prefer "Ctrl -") and the Ctrl++ shortcut label displays as "Ctrl+Equals" (even worse - in the interest of user experience, I would prefer "Ctrl +"):

menuBar_view_zoomIn.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, ActionEvent.CTRL_MASK));

enter image description here

I want Ctrl++ to display as "Ctrl +" and Ctrl+- to display as "Ctrl -". How can this be done?

joshreesjones
  • 1,934
  • 5
  • 24
  • 42
  • What key does "Ctrl++" represent. Like we know "Ctrl +" "+" asks user to press ctrl and + but what does "Ctrl++" mean ?? What is the intention behind doing so – Sanyam Goel Aug 08 '13 at 05:40
  • `KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS,..` Umm.. and you expected to see a `+` sign? Why? – Andrew Thompson Aug 08 '13 at 05:43
  • +1 for nice idea, AFAIK this is done in the few custom Look and Feels, I saw this label placed on left, right, and bottom, – mKorbel Aug 08 '13 at 05:45
  • Popup window is container, you can to relayout standard popup and add JButtons layed by GridLayout(CENTER), and put the same GridLayout with JLabel to the EAST, WEST..., this JLabel can contians anything, note, (funny issue, maybe bug, maybe feature with using popup for another reasons) popup must be pack() before visible, everytime – mKorbel Aug 08 '13 at 05:49
  • "Ctrl+ +" means pressing Control and the Plus key. – joshreesjones Aug 08 '13 at 06:04
  • @AndrewThompson, I expected to see "Ctrl-Equals", but I want it to display as "Ctrl +". Sorry for the ambiguity. – joshreesjones Aug 08 '13 at 06:05
  • why do you want to confuse your users? They are accustomed to see the _+_ between keys they are supposed to press simultaneously .. (at least in win) – kleopatra Aug 08 '13 at 08:43

2 Answers2

3

not an answer, you need to search for

  • paint() to heavy, paintComponent() for lightweight JPopup, JMenu (for custom painting can be switch to isHeavyWeight...)

  • overlay JLabel into container (few question about JTable by @Guillaume Polet and @Robin)

  • create own JMenu/JPopup (see my comment to your question)

enter image description here

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.basic.BasicArrowButton;

public class ComboBoxMenuExample extends JFrame {

    public ComboBoxMenuExample() {
        super("ComboBoxMenu Example");
        String[] itemStr = {"name", "Red", "Blue", "number", "255,0,0", "0,0,255",
            /*separator*/ "system", "control", "controlHighlight", "controlShadow", "text"};
        JMenuItem[] menuItems = new JMenuItem[7];
        menuItems[0] = new JMenuItem(itemStr[1]);
        menuItems[1] = new JMenuItem(itemStr[2]);
        menuItems[2] = new JMenuItem(itemStr[4]);
        menuItems[3] = new JMenuItem(itemStr[5]);
        menuItems[4] = new JMenuItem(itemStr[8]);
        menuItems[5] = new JMenuItem(itemStr[9]);
        menuItems[6] = new JMenuItem(itemStr[10]);
        JMenu[] menus = new JMenu[4];
        menus[0] = new JMenu(itemStr[0]);
        menus[1] = new JMenu(itemStr[3]);
        menus[2] = new JMenu(itemStr[6]);
        menus[3] = new JMenu(itemStr[7]);
        menus[0].add(menuItems[0]);
        menus[0].add(menuItems[1]);
        menus[1].add(menuItems[2]);
        menus[1].add(menuItems[3]);
        menus[3].add(menuItems[4]);
        menus[3].add(menuItems[5]);
        menus[2].add(menus[3]);
        menus[2].add(menuItems[6]);
        JMenu menu = ComboMenuBar.createMenu(menuItems[0].getText());
        menu.add(menus[0]);
        menu.add(menus[1]);
        menu.addSeparator();
        menu.add(menus[2]);
        ComboMenuBar comboMenu = new ComboMenuBar(menu);
        JComboBox combo = new JComboBox();
        combo.addItem(itemStr[1]);
        combo.addItem(itemStr[2]);
        combo.addItem(itemStr[4]);
        combo.addItem(itemStr[5]);
        combo.addItem(itemStr[8]);
        combo.addItem(itemStr[9]);
        combo.addItem(itemStr[10]);
        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(new ComboPanel("Fake ComboBox", comboMenu));
        getContentPane().add(new ComboPanel("ComboBox", combo));
    }

    class ComboPanel extends JPanel {

        ComboPanel(String title, JComponent c) {
            setLayout(new FlowLayout());
            setBorder(new TitledBorder(title));
            add(c);
        }
    }

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception evt) {
        }
        ComboBoxMenuExample frame = new ComboBoxMenuExample();
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.setSize(370, 100);
        frame.setVisible(true);
    }
}

class ComboMenuBar extends JMenuBar {

    JMenu menu;
    Dimension preferredSize;

    public ComboMenuBar(JMenu menu) {
        this.menu = menu;
        Color color = UIManager.getColor("Menu.selectionBackground");
        UIManager.put("Menu.selectionBackground", UIManager.getColor("Menu.background"));
        UIManager.put("Menu.selectionBackground", color);
        menu.updateUI();
        MenuItemListener listener = new MenuItemListener();
        setListener(menu, listener);
        add(menu);
    }

    class MenuItemListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            JMenuItem item = (JMenuItem) e.getSource();
            menu.setText(item.getText());
            menu.requestFocus();
        }
    }

    private void setListener(JMenuItem item, ActionListener listener) {
        if (item instanceof JMenu) {
            JMenu menu1 = (JMenu) item;
            int n = menu1.getItemCount();
            for (int i = 0; i < n; i++) {
                setListener(menu1.getItem(i), listener);
            }
        } else if (item != null) { // null means separator
            item.addActionListener(listener);
        }
    }

    public String getSelectedItem() {
        return menu.getText();
    }

    @Override
    public void setPreferredSize(Dimension size) {
        preferredSize = size;
    }

    @Override
    public Dimension getPreferredSize() {
        if (preferredSize == null) {
            Dimension sd = super.getPreferredSize();
            Dimension menuD = getItemSize(menu);
            Insets margin = menu.getMargin();
            Dimension retD = new Dimension(menuD.width, margin.top
                    + margin.bottom + menuD.height);
            menu.setPreferredSize(retD);
            preferredSize = retD;
        }
        return preferredSize;
    }

    private Dimension getItemSize(JMenu menu) {
        Dimension d = new Dimension(0, 0);
        int n = menu.getItemCount();
        for (int i = 0; i < n; i++) {
            Dimension itemD;
            JMenuItem item = menu.getItem(i);
            if (item instanceof JMenu) {
                itemD = getItemSize((JMenu) item);
            } else if (item != null) {
                itemD = item.getPreferredSize();
            } else {
                itemD = new Dimension(0, 0); // separator
            }
            d.width = Math.max(d.width, itemD.width);
            d.height = Math.max(d.height, itemD.height);
        }
        return d;
    }

    public static class ComboMenu extends JMenu {

        ArrowIcon iconRenderer;

        public ComboMenu(String label) {
            super(label);
            iconRenderer = new ArrowIcon(SwingConstants.SOUTH, true);
            setBorder(new EtchedBorder());
            setIcon(new BlankIcon(null, 11));
            setHorizontalTextPosition(JButton.LEFT);
            setFocusPainted(true);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Dimension d = this.getPreferredSize();
            int x = Math.max(0, d.width - iconRenderer.getIconWidth() - 3);
            int y = Math.max(0,
                    (d.height - iconRenderer.getIconHeight()) / 2 - 2);
            iconRenderer.paintIcon(this, g, x, y);
        }
    }

    public static JMenu createMenu(String label) {
        return new ComboMenu(label);
    }
}

class ArrowIcon implements Icon, SwingConstants {

    private static final int DEFAULT_SIZE = 11;
    //private static final int DEFAULT_SIZE = 5;
    private int size;
    private int iconSize;
    private int direction;
    private boolean isEnabled;
    private BasicArrowButton iconRenderer;

    public ArrowIcon(int direction, boolean isPressedView) {
        this(DEFAULT_SIZE, direction, isPressedView);
    }

    public ArrowIcon(int iconSize, int direction, boolean isEnabled) {
        this.size = iconSize / 2;
        this.iconSize = iconSize;
        this.direction = direction;
        this.isEnabled = isEnabled;
        iconRenderer = new BasicArrowButton(direction);
    }

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
        iconRenderer.paintTriangle(g, x, y, size, direction, isEnabled);
    }

    @Override
    public int getIconWidth() {
        //int retCode;
        switch (direction) {
            case NORTH:
            case SOUTH:
                return iconSize;
            case EAST:
            case WEST:
                return size;
        }
        return iconSize;
    }

    @Override
    public int getIconHeight() {
        switch (direction) {
            case NORTH:
            case SOUTH:
                return size;
            case EAST:
            case WEST:
                return iconSize;
        }
        return size;
    }
}

class BlankIcon implements Icon {

    private Color fillColor;
    private int size;

    public BlankIcon() {
        this(null, 11);
    }

    public BlankIcon(Color color, int size) {
        //UIManager.getColor("control")
        //UIManager.getColor("controlShadow")
        fillColor = color;
        this.size = size;
    }

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
        if (fillColor != null) {
            g.setColor(fillColor);
            g.drawRect(x, y, size - 1, size - 1);
        }
    }

    @Override
    public int getIconWidth() {
        return size;
    }

    @Override
    public int getIconHeight() {
        return size;
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
0

insted of menuBar_view_zoomIn.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, ActionEvent.CTRL_MASK));

use menuBar_view_zoomIn.setAccelerator(KeyStroke.getKeyStroke(new Character('-'), ActionEvent.CTRL_MASK));

hemant
  • 27
  • 6