Как создать многослойный JComboBox

Я создаю симулятор с использованием Java Swing. Я использовал JComboBox для отображения единиц коммунальных услуг, таких как «кВт, кл, км» и т. д., для измерения мощности, воды и расстояния. Добавить кучу элементов в JComboBox просто. Пользователь выбирает единицу измерения, и JFrame сохраняет выбор при нажатии кнопки «Сохранить».

    JComboBox comboBox = new JComboBox();
    for(ValueUnits u: ValueUnits.values()){
        comboBox.addItem(u.returnUnits());
    }

    comboBox.setSelectedIndex(-1);
    unitColumn.setCellEditor(new DefaultCellEditor(comboBox));

Теперь я хочу создать многослойный JComboBox (возможно, JMenu?). Функция такого должна вести себя как многослойное JMenu. Когда щелкнут JComboBox, он покажет первый слой — категорию, такую ​​как «Электричество, Вода, Расстояние…», Затем, когда указатель мыши наведет курсор на Электричество, появится список единиц Электричества, таких как «кВт, МВт, Вт… " покажет. Эти коллекции извлекаются из Enumerations. Интересно, какой самый правильный способ создать такой компонент.

Спасибо большое мир!


person William    schedule 13.08.2014    source источник


Ответы (3)


Может быть, использовать 2 поля со списком? То есть вы выбираете значение в первом, а единицы отображаются во втором:

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

public class ComboBoxTwo extends JPanel implements ActionListener
{
    private JComboBox<String> mainComboBox;
    private JComboBox<String> subComboBox;
    private Hashtable<String, String[]> subItems = new Hashtable<String, String[]>();

    public ComboBoxTwo()
    {
        String[] items = { "Select Item", "Color", "Shape", "Fruit" };
        mainComboBox = new JComboBox<String>( items );
        mainComboBox.addActionListener( this );

        //  prevent action events from being fired when the up/down arrow keys are used
        mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
        add( mainComboBox );

        //  Create sub combo box with multiple models

        subComboBox = new JComboBox<String>();
        subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
        add( subComboBox );

        String[] subItems1 = { "Select Color", "Red", "Blue", "Green" };
        subItems.put(items[1], subItems1);

        String[] subItems2 = { "Select Shape", "Circle", "Square", "Triangle" };
        subItems.put(items[2], subItems2);

        String[] subItems3 = { "Select Fruit", "Apple", "Orange", "Banana" };
        subItems.put(items[3], subItems3);
    }

    public void actionPerformed(ActionEvent e)
    {
        String item = (String)mainComboBox.getSelectedItem();
        Object o = subItems.get( item );

        if (o == null)
        {
            subComboBox.setModel( new DefaultComboBoxModel() );
        }
        else
        {
            subComboBox.setModel( new DefaultComboBoxModel( (String[])o ) );
        }
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new ComboBoxTwo() );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}
person camickr    schedule 14.08.2014
comment
Спасибо камикр! Это делает именно то, что я хочу. - person William; 15.08.2014

Используй это...

public class ComboLayer extends javax.swing.JPanel {

String Category1 = null;
String Category2 = null;
String Category3 = null;
Hashtable<String, String> hsItems;


public ComboLayer() {
    this.hsItems = new Hashtable<>();

    hsItems.put("Main", "Power,Water,Distance");
    hsItems.put("Power", "KW,MW,W");
    hsItems.put("Water", "ML,L,KL");
    hsItems.put("Distance", "CM,M,KM");
    initComponents();
    String[] item = hsItems.get("Main").split(",");
    for (String i : item) {
        cmbItem.addItem(i);
    }
    cmbItem.addItem("Back");
    cmbItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            String selectText = null;
            selectText = (String) cmbItem.getSelectedItem();
            Enumeration enmKeys = hsItems.keys();
            while (enmKeys.hasMoreElements()) {
                String sKey = (String) enmKeys.nextElement();
                if (selectText.equalsIgnoreCase("back")) {
                    if (hsItems.get(sKey).contains(cmbItem.getItemAt(0).toString())) {
                        Enumeration enumkeysBack = hsItems.keys();
                        while (enumkeysBack.hasMoreElements()) {
                            String sKeyBack = (String) enumkeysBack.nextElement();
                            if (hsItems.get(sKeyBack).contains(sKey)) {
                                String[] item = hsItems.get(sKeyBack).split(",");
                                cmbItem.removeAllItems();
                                for (String i : item) {
                                    cmbItem.addItem(i);
                                }
                                if (!sKeyBack.equalsIgnoreCase("Main")) {
                                    cmbItem.addItem("Back");
                                }
                                 break;
                            }

                        }
                    }
                } else if (sKey.contains(selectText)) {
                    String[] item = hsItems.get(sKey).split(",");
                    cmbItem.removeAllItems();
                    for (String i : item) {
                        cmbItem.addItem(i);
                    }
                    if (!sKey.equalsIgnoreCase("Main")) {
                        cmbItem.addItem("Back");
                    }
                    break;
                }
            }

        }
    });
}

public static void main(String... arg) {
    ComboLayer cmbLyr = new ComboLayer();
    JDialog dg = new JDialog();
    dg.add(cmbLyr);
    dg.setVisible(true);
}
person Tej Kiran    schedule 14.08.2014

Вот комбинация с эффектом пользовательского всплывающего окна JMenu. Фактическое всплывающее окно скрыто, и при необходимости отображается второе всплывающее окно.

При выборе JMenuItem комбинация заполняется только этим одним элементом, отображаемым в формате «хлебных крошек».

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;

public class JMenuComboBoxDemo implements Runnable
{
  private Map<String, String[]> menuData;
  private JComboBox<String> combo;
  private AbstractButton arrowButton;
  private JPopupMenu popupMenu;
  private List<String> flattenedData;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new JMenuComboBoxDemo());
  }

  public JMenuComboBoxDemo()
  {
    menuData = new HashMap<String, String[]>();
    menuData.put("Colors",  new String[]{"Black", "Blue"});
    menuData.put("Flavors", new String[]{"Lemon", "Lime"});

    popupMenu = new JPopupMenu();
    popupMenu.setBorder(new MatteBorder(1, 1, 1, 1, Color.DARK_GRAY));

    List<String> categories = new ArrayList<String>(menuData.keySet());
    Collections.sort(categories);

    // copy of the menuData, flattened into a List
    flattenedData = new ArrayList<String>();

    for (String category : categories)
    {
      JMenu menu = new JMenu(category);
      for (String itemName : menuData.get(category))
      {
        menu.add(createMenuItem(itemName));
        flattenedData.add(category + " > " + itemName);
      }
      popupMenu.add(menu);
    }

    combo = new JComboBox<String>();
    combo.setPrototypeDisplayValue("12345678901234567890");
    combo.setUI(new EmptyComboBoxUI());

    for (Component comp : combo.getComponents())
    {
      if (comp instanceof AbstractButton)
      {
        arrowButton = (AbstractButton) comp;
      }
    }

    arrowButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        setPopupVisible(! popupMenu.isVisible());
      }
    });

    combo.addMouseListener(new MouseAdapter()
    {
      @Override
      public void mouseClicked(MouseEvent e)
      {
        setPopupVisible(! popupMenu.isVisible());
      }
    });
  }

  public void run()
  {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = frame.getContentPane();
    c.setLayout(new FlowLayout());
    c.add(new JLabel("Options"));
    c.add(combo);

    frame.setSize(300, 200);
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
  }

  /*
   * Toggle the visibility of the custom popup.
   */
  private void setPopupVisible(boolean visible)
  {
    if (visible)
    {
      popupMenu.show(combo, 0, combo.getSize().height);
    }
    else
    {
      popupMenu.setVisible(false);
    }
  }

  /*
   * Create a JMenuItem whose listener will display
   * the item in the combo.
   */
  private JMenuItem createMenuItem(final String name)
  {
    JMenuItem item = new JMenuItem(name);
    item.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        setComboSelection(name);
      }
    });
    return item;
  }

  /*
   * Search for the given name in the flattened list of menu items.
   * If found, add that item to the combo and select it.
   */
  private void setComboSelection(String name)
  {
    Vector<String> items = new Vector<String>();

    for (String item : flattenedData)
    {
      /*
       * We're cheating here: if two items have the same name
       * (Fruit->Orange and Color->Orange, for example)
       * the wrong one may get selected. This should be more sophisticated
       * (left as an exercise to the reader)
       */
      if (item.endsWith(name))
      {
        items.add(item);
        break;
      }
    }

    combo.setModel(new DefaultComboBoxModel<String>(items));

    if (items.size() == 1)
    {
      combo.setSelectedIndex(0);
    }
  }

  /*
   * Prevents the default popup from being displayed
   */
  class EmptyComboBoxUI extends MetalComboBoxUI  
  {
    @Override
    protected ComboPopup createPopup()  
    {  
      BasicComboPopup thePopup = (BasicComboPopup) super.createPopup();  
      thePopup.setPreferredSize(new Dimension(0,0));  // oh, the horror!
      return thePopup;  
    }  
  }
}
person splungebob    schedule 14.08.2014