Java - 如何显示一个输入对话框,其中包含一个下拉列表,每个项目都有一个图标?

Java - How to show an input dialog having a dropdown list with an icon for each item?

我在我的 swing 应用程序中使用这个 Java 代码来显示一个输入对话框,其中有一个下拉 selection 列表,因此用户可以 select 从中选择一个项目名单:

String[] carModelsArray = { "Honda", "Mitsubishi", "Toyota" };
String selectedValue = (String)JOptionPane.showInputDialog( null, "Select a car model from the list below:", "Car model...",
                                        JOptionPane.QUESTION_MESSAGE, 
                                        null, 
                                        carModelsArray,
                                        carModelsArray[ 0 ] );

这段代码工作正常,但我想知道我是否也可以为 selection 列表中的每个项目添加一个图标,所以下拉列表 selection 列表将如下所示:

我尝试将此列表中的项目设置为 JLabel 项目,但在下拉列表中呈现时,JLabel 对象全部转换为字符串值,就好像它调用 JLabel.toString() 方法一样为列表中的每个项目获取其值。

那么有没有办法做到这一点?

简短的回答,不是你这样做的方式。长答案,更像是...

import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.kaizen.icons.AddIcon;
import org.kaizen.icons.DeleteIcon01;
import org.kaizen.icons.DeleteIcon02;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultComboBoxModel model = new DefaultComboBoxModel<Car>();
                model.addElement(new Car(new AddIcon(16, 16), "Honda"));
                model.addElement(new Car(new DeleteIcon01(16, 16), "Mitsubishi"));
                model.addElement(new Car(new DeleteIcon02(16, 16), "Tyota"));

                JComboBox cb = new JComboBox(model);
                cb.setRenderer(new CarListCellRenderer());

                int result = JOptionPane.showConfirmDialog(null, cb, "Select a car model from the list below", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.OK_OPTION) {
                    Car car = (Car) cb.getSelectedItem();
                }

            }
        });
    }

    public static class CarListCellRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            System.out.println(value);
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value instanceof Car) {
                Car car = (Car) value;
                setIcon(car.getIcon());
                setText(car.getText());
            } else {
                setIcon(null);
            }
            return this;
        }

    }

    public static class Car {

        private Icon icon;
        private String text;

        public Car(Icon icon, String text) {
            this.icon = icon;
            this.text = text;
        }

        public Icon getIcon() {
            return icon;
        }

        public String getText() {
            return text;
        }

    }

}

基本上,您需要控制组合框并提供您自己的自定义 ListCellRedender,它可以提供您想要的输出...

感谢 MadProgrammer 的有用回答,我能够使用他的想法找到解决方案。最终结果如下所示:

这是我使用的代码:

public class MyClass extends JFrame {
    private JComboBox inputComboBox = null;

    private void button6ActionPerformed() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JPanel inputPanel = createPanel();

                int result = JOptionPane.showConfirmDialog(null, inputPanel, "Car model...", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.OK_OPTION) {
                    System.out.println( (String)inputComboBox.getSelectedItem() );
                }
            }
        });   
    }

    private JPanel createPanel() {
        CellConstraints cc = new CellConstraints();

        //1. Create JPanel :
            JPanel inputPanel = new JPanel();
            inputPanel.setLayout(new FormLayout(
                new ColumnSpec[] {
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13)),
                    FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
                    new ColumnSpec(Sizes.dluX(13))
                },
                new RowSpec[] {
                    new RowSpec(Sizes.dluY(13)),
                    FormFactory.LINE_GAP_ROWSPEC,
                    new RowSpec(Sizes.dluY(13)),
                    FormFactory.LINE_GAP_ROWSPEC,
                    new RowSpec(Sizes.dluY(13))
                }));

        //2. Create JLabel :
            JLabel inputLabel = new JLabel( "Select a car model from the list below :" );
            inputPanel.add( inputLabel, cc.xywh( 1, 1, 15, 1 ) );

        //3. Create ComboBox :
            DefaultComboBoxModel model = new DefaultComboBoxModel();
            model.addElement("Honda");
            model.addElement("Mitsubishi");
            model.addElement("Toyota");

            inputComboBox = new JComboBox( model );
            inputComboBox.setRenderer( new ComboBoxRenderer() );

            inputPanel.add( inputComboBox, cc.xywh(1, 3, 10, 2 ) );

         return inputPanel;
    }
}

class ComboBoxRenderer extends JLabel implements ListCellRenderer { 
    public Component getListCellRendererComponent(
                    JList list,
                    Object selectedCarModel,
                    int selectedModelIndex,
                    boolean isSelected,
                    boolean cellHasFocus) {
        //1. Set the list item text, icon & styling properties :
            String carModel = (String)selectedCarModel;
            String iconPath = "/images/" + carModel.toLowerCase() + ".png";  // The icon file should have the same name of the car model.
            URL iconURL = getClass().getResource( iconPath );

            setText( carModel );
            setIcon( new ImageIcon( iconURL ) );
            setPreferredSize( new Dimension( list.getWidth(), 30 ) );

        //2. Set the selected/deselected list item selection colors : 
            if (isSelected) {
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }

        return this;
    }
}