问题
I need to add a label on the right hand side of a JMenuItem
, like the labels shown below:
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));
I want Ctrl++ to display as "Ctrl +" and Ctrl+- to display as "Ctrl -". How can this be done?
回答1:
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)
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;
}
}
来源:https://stackoverflow.com/questions/18118536/how-can-i-add-to-or-change-a-label-on-a-jmenuitem