在编辑字段中具有不同文本的可编辑 JComboBox

Editable JComboBox with different text in edit field

我一直在寻找一种方法来使 JComboBox 列表中的项目正常显示,但在编辑字段中只显示一个数字。

我遇到了这段代码(只是根据我的需要稍作修改):

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

public class ComboBoxItem extends JFrame implements ActionListener {
    public ComboBoxItem() {
        Vector model = new Vector();
        model.addElement( new Item(1, "car" ) );
        model.addElement( new Item(2, "plane" ) );
        model.addElement( new Item(3, "train" ) );
        model.addElement( new Item(4, "boat" ) );

        JComboBox comboBox;

        comboBox = new JComboBox( model );
        comboBox.addActionListener( this );
        getContentPane().add(comboBox, BorderLayout.NORTH );

        comboBox = new JComboBox( model );

        // I want the comboBox editable.
        //comboBox.setEditable(true);

        comboBox.setRenderer( new ItemRenderer() );
        comboBox.addActionListener( this );
        getContentPane().add(comboBox, BorderLayout.SOUTH );
    }

    public void actionPerformed(ActionEvent e) {
        JComboBox comboBox = (JComboBox)e.getSource();
        Item item = (Item)comboBox.getSelectedItem();
        System.out.println( item.getId() + " : " + item.getDescription() );
    }

    class ItemRenderer extends BasicComboBoxRenderer {
        public Component getListCellRendererComponent(
            JList list, Object value, int index,
            boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index,
                isSelected, cellHasFocus);

            if (value != null) {
                Item item = (Item)value;
                setText( item.getDescription().toUpperCase() );
            }

            if (index == -1) {
                Item item = (Item)value;
                setText( "" + item.getId() );
            }
            return this;
        }
    }

    class Item {
        private int id;
        private String description;

        public Item(int id, String description) {
            this.id = id;
            this.description = description;
        }

        public int getId() {
            return id;
        }

        public String getDescription() {
            return description;
        }

        public String toString() {
            return description;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new ComboBoxItem();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
     }     
}

这很好用,直到我使用 comboBox.setEditable(true); 使组合框可编辑。

背景资料:

我计划在用户在编辑字段中键入时使用数据库中的对象填充弹出列表。当用户随后从弹出列表中选择一个项目时,编辑字段应仅显示对象的 id,但弹出列表应显示更多信息,以便用户做出明智的选择。

任何人都可以帮助我完成这项工作,无论是打开还是关闭可编辑?

如果我正确理解你的要求,你可以使用你自己的javax.swing.ComboBoxEditor

我刚刚以您的示例为例,并添加了一个非常快速的'n'dirty ComboBoxEditor,它使用javax.swing.JTextField并将其设置为秒 ComboBox 编辑器。

也许这个例子向您展示了一种解决问题的方法。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class ComboBoxItem extends JFrame implements ActionListener {

    public ComboBoxItem() {
        final Vector model = new Vector();
        model.addElement(new Item(1, "car"));
        model.addElement(new Item(2, "plane"));
        model.addElement(new Item(3, "train"));
        model.addElement(new Item(4, "boat"));

        JComboBox comboBox;

        comboBox = new JComboBox(model);
        comboBox.addActionListener(this);
        this.getContentPane().add(comboBox, BorderLayout.NORTH);

        comboBox = new JComboBox(model);

        // I want the comboBox editable.
        comboBox.setEditable(true);

        comboBox.setRenderer(new ItemRenderer());
        comboBox.setEditor(new MyComboBoxEditor()); ///<------- Quick'n'Dirty editor added
        comboBox.addActionListener(this);
        this.getContentPane().add(comboBox, BorderLayout.SOUTH);
    }

    @Override
    public void actionPerformed(final ActionEvent e) {
        final JComboBox comboBox = (JComboBox) e.getSource();
        final Item item = (Item) comboBox.getSelectedItem();
        System.out.println(item.getId() + " : " + item.getDescription());
    }

    class MyComboBoxEditor implements ComboBoxEditor {

        JTextField editor;
        Item       editedItem;

        @Override
        public void addActionListener(final ActionListener l) {

        }

        @Override
        public Component getEditorComponent() {
            if (this.editor == null) {
                this.editor = new JTextField();
            }
            return this.editor;
        }

        @Override
        public Object getItem() {
            return this.editedItem;
        }

        @Override
        public void removeActionListener(final ActionListener l) {
            // TODO Auto-generated method stub

        }

        @Override
        public void selectAll() {
            // TODO Auto-generated method stub

        }

        @Override
        public void setItem(final Object anObject) {
            this.editedItem = (Item) anObject;
            this.editor.setText(String.valueOf(this.editedItem.getId()));
        }

    }

    class ItemRenderer extends BasicComboBoxRenderer {

        @Override
        public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected,
                final boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value != null) {
                final Item item = (Item) value;
                this.setText(item.getDescription().toUpperCase());
            }

            if (index == -1) {
                final Item item = (Item) value;
                this.setText("" + item.getId());
            }

            return this;
        }
    }

    class Item {

        private final int    id;
        private final String description;

        public Item(final int id, final String description) {
            this.id = id;
            this.description = description;
        }

        public int getId() {
            return this.id;
        }

        public String getDescription() {
            return this.description;
        }

        @Override
        public String toString() {
            return this.description;
        }
    }

    public static void main(final String[] args) {
        final JFrame frame = new ComboBoxItem();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

你可以在第47行和第88行之间找到编辑器。

此致

您需要覆盖组合框的默认编辑器,因为当您将组合框设置为可编辑时,它会使用编辑器呈现您在下拉列表中选择的内容。

下面是使用 BasicComboBoxEditor 的一种实现方式。您只需要覆盖 setItem 方法。

comboBox.setEditor(new ItemEditor());

class ItemEditor extends BasicComboBoxEditor {
    public void setItem(Object anObject) {
        Item item = (Item) anObject;
        editor.setText(item.getId() + "");
    }
}