2012-11-27 168 views
2

我相信可以通过为元素等创建JMenu来创建JComboBoxes下的子菜单,这本质上意味着创建您自己的自定义组件。我也看了几个例子,它非常复杂,大多数似乎有某种问题或其他问题。JComboBox子菜单项

所以基本上我的问题是以某种方式以一种相当简单的方式创建看起来像JComboBox的东西,但也支持子菜单。

+2

可能,是的,我猜想;容易,我怀疑它。我认为你会遇到的最大问题是列表中的项目只是“橡皮图章”渲染器,它们不是实际的“实时”组件,这会使生活非常混乱:P – MadProgrammer

+0

从层次结构中进行选择:也许['JTree'](http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html)或['Outline'](http://codereview.stackexchange.com/a/4447/ 6692)? – trashgod

回答

2

这是一个例子中发现: http://www.java2s.com/Code/Java/Swing-Components/ComboBoxMenuExample.htm

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() { 
    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")); 
menu.updateUI(); 
UIManager.put("Menu.selectionBackground", color); 

MenuItemListener listener = new MenuItemListener(); 
setListener(menu, listener); 

add(menu); 
} 

class MenuItemListener implements ActionListener { 
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 menu = (JMenu) item; 
    int n = menu.getItemCount(); 
    for (int i = 0; i < n; i++) { 
    setListener(menu.getItem(i), listener); 
    } 
} else if (item != null) { // null means separator 
    item.addActionListener(listener); 
} 
} 

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

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

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); 
} 

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); 
} 

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

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

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; 
} 

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); 
} 
} 

public int getIconWidth() { 
return size; 
} 

public int getIconHeight() { 
return size; 
} 
} 

我这里测试并运行完美 似乎有点复杂,但是如果你的代码好好看看就明白了

+1

这是很多代码的问题。也许你可以解释它对我们其他人的作用。 –

+2

或者你只是发布你自己不明白的代码吗? –

+1

我在Google上搜索时也发现了这个例子,它相当复杂且硬编码。这不是一个快速解决方案的好例子... –