代码之家  ›  专栏  ›  技术社区  ›  QA_Col

将ComboBoxEditor接口与自定义JComponent一起使用,并允许编辑和显示列表

  •  0
  • QA_Col  · 技术社区  · 6 年前

    我在查文件。

    ... 我正在尝试使用我的自定义组合框来实现这个接口 ComboBoxEditor .

    这是我的完整代码。。。

    我有一个 JPanel 具有 JComponents

    class ThePanel extends JPanel {
    
      private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
    
      private final JToggleButton jtbEnabled = new JToggleButton();
      private final JToggleButton jtbDefaultOperation = new JToggleButton();
      private final JTextField jtfText = new JTextField("", 0);
    
      private final JPanel jpThePanel = new JPanel();
    
      public ThePanel(Font extFont) {
        this(new TheModel(), extFont);
      }
    
      public ThePanel(TheModel data, Font extFont) {
        super();
        intFont = extFont;
        initEnabled();
        initDefaultOperation();
        initText();
        setData(data);
    
        jpThePanel.setLayout(new BoxLayout(jpThePanel, BoxLayout.LINE_AXIS));
        jpThePanel.add(Box.createRigidArea(new Dimension(2, 0)));
        jpThePanel.add(jtbEnabled);
        jpThePanel.add(jtbDefaultOperation);
        jpThePanel.add(jtfText);
        jpThePanel.add(Box.createRigidArea(new Dimension(2, 0)));
        init();
      }
    
      private void init() {
        setFont(intFont);
        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        setBackground(new Color(0, 0, 0, 0/*64*/));
        add(jpThePanel);
        Dimension d = getMinimumSize();
        setSize(d);
        setPreferredSize(d);
        setMaximumSize(d);
        setSize(d);
      }
    
      private void initEnabled() {
        jtbEnabled.setFont(intFont);
        jtbEnabled.setIcon(new ImageIcon(getClass().getResource("Unselected.png")));
        jtbEnabled.setSelectedIcon(new ImageIcon(getClass().getResource("Selected.png")));
      }
    
      private void initDefaultOperation() {
        jtbDefaultOperation.setFont(intFont);
        jtbDefaultOperation.setIcon(new ImageIcon(getClass().getResource("Insert.png")));
        jtbDefaultOperation.setSelectedIcon(new ImageIcon(getClass().getResource("Extract.png")));
        jtbDefaultOperation.setDisabledIcon(new ImageIcon(getClass().getResource("DisabledInsert.png")));
        jtbDefaultOperation.setDisabledSelectedIcon(new ImageIcon(getClass().getResource("DisabledExtract.png")));
      }
    
      private void initText() {
        jtfText.setFont(intFont);
      }
    
      public TheModel getData() {
        return new TheModel(
            jtbEnabled.isSelected(),
            jtbDefaultOperation.isSelected(),
            jtfText.getText()
        );
      }
    
      public void setData(TheModel data) {
        jtbEnabled.setSelected(data.getEnabled());
        jtbDefaultOperation.setEnabled(data.getEnabled());
        jtbDefaultOperation.setSelected(data.getDefaultOperation());
        jtfText.setText(data.getText());
      }
    
      public void selectAll() {
        jtfText.selectAll();
      }
    
    }
    

    现在,我有了它内部组件的模型数据。。。

    class TheModel {
    
      private Boolean enabled = true;
      private Boolean defaultOperation = true;
      private String text = "";
    
      public TheModel() {
        this("");
      }
    
      public TheModel(String text) {
        this(true, text);
      }
    
      public TheModel(Boolean defaultOperation, String text) {
        this(true, defaultOperation, text);
      }
    
      public TheModel(Boolean enabled, Boolean defaultOperation, String text) {
        this.enabled = enabled;
        this.defaultOperation = defaultOperation;
        this.text = text;
      }
    
      public Boolean getEnabled() {
        return enabled;
      }
    
      public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
      }
    
      public Boolean getDefaultOperation() {
        return defaultOperation;
      }
    
      public void setDefaultOperation(Boolean defaultOperation) {
        this.defaultOperation = defaultOperation;
      }
    
      public String getText() {
        return text;
      }
    
      public void setText(String text) {
        this.text = text;
      }
    
      @Override
      public String toString() {
        return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation + ", text=" + text + '}';
      }
    
    }
    

    我想使用我的自定义组件( ThePanel JComboBox 操纵内部元素 JToggleButton JTextField 组合框编辑器 接口 . 这个 ListCellRenderer 界面试图显示列表。。。因为只执行 组合框编辑器 不起作用。

    class TheComboBoxEditor implements ComboBoxEditor, ListCellRenderer {
    
      protected ThePanel editor;
      private final EventListenerList listenerList = new EventListenerList();
    
      public TheComboBoxEditor(Font extFont) {
        editor = new ThePanel(extFont);
      }
    
      private void fireActionEvent(ActionEvent evt) {
        for (ActionListener al : listenerList.getListeners(ActionListener.class)) {
          al.actionPerformed(evt);
        }
      }
    
      @Override
      public void addActionListener(ActionListener l) {
        listenerList.add(ActionListener.class, l);
      }
    
      @Override
      public void removeActionListener(ActionListener l) {
        listenerList.remove(ActionListener.class, l);
      }
    
      @Override
      public void selectAll() {
        editor.selectAll();
        editor.requestFocus();
      }
    
      @Override
      public Object getItem() {
        return editor.getData();
      }
    
      @Override
      public void setItem(Object anObject) {
        if (anObject != null) {
          if (anObject instanceof TheModel) {
            editor.setData((TheModel) anObject);
          }
          if (anObject instanceof String) {
            editor.setData(new TheModel(anObject.toString()));
          }
        } else {
          editor.setData(new TheModel());
        }
      }
    
      @Override
      public Component getEditorComponent() {
        return editor;
      }
    
      @Override
      public Component getListCellRendererComponent(JList list, Object value,
          int index, boolean isSelected, boolean cellHasFocus) {
        TheModel data = (TheModel) value;
        editor.setData(data);
        return editor;
      }
    
    }
    

    现在,我举一个例子 TheComboBoxEditor .

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class ExampleComboBoxEditor extends JFrame {
    
      public ExampleComboBoxEditor() {
        TheModel items[] = {
          new TheModel(true, true, "True, True"),
          new TheModel(true, false, "True, False"),
          new TheModel(false, true, "False, True"),
          new TheModel(false, false, "False, False")};
    
        String strings[] = {
          "True, True", "True, False", "False, True", "False, False"};
    
        JComboBox internalComboBox = new JComboBox(items);
        internalComboBox.setEditable(true);
        internalComboBox.setEditor(new TheComboBoxEditor(this.getFont()));
        internalComboBox.setMaximumRowCount(4);
        internalComboBox.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
          }
        });
    
        JComboBox stringsComboBox = new JComboBox(strings);
        stringsComboBox.setEditable(true);
        stringsComboBox.setMaximumRowCount(4);
        stringsComboBox.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
          }
        });
    
        JPanel outer = new JPanel();
        outer.add(internalComboBox);
        outer.add(stringsComboBox);
        add(outer);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      }
    
      public static void main(String[] args) {
        ExampleComboBoxEditor app = new ExampleComboBoxEditor();
        app.setSize(840, 240);
        app.setVisible(true);
      }
    }
    

    现在,我有我的疑问(对我来说,这些方法的目标并不明确)。。。

    selectAll() 我该怎么办?

    2.我不止一个 文本框 其他组件2 触发器按钮 那也是。 有什么建议 addActionListener(ActionListener l) removeActionListener(ActionListener l) 方法?

    http://www.java2s.com/Tutorials/Java/Swing_How_to/JComboBox/Add_JCheckBox_components_to_JComboBox.htm

    enter image description here enter image description here

    如您所见,列表显示为。。。

    enter image description here enter image description here

    3.我看不到正确显示的组件列表。

    4.我不能编辑我的 jtfText , jtbEnabled jtbDefaultOperation 组件(永久存储状态/属性)。

    编辑

    基于 aterai TheModel

    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    
    /*
    //https://stackoverflow.com/posts/53046908/revisions
    
    javac -Xlint:unchecked -Xlint:deprecation -encoding utf8 -d /Users/bz/Documentos/Java/classes /Users/jose/Documentos/Java/ExampleComboBoxEditorNOIndex.java
    java -cp /Users/bz/Documentos/Java/classes ExampleComboBoxEditorNOIndex &
    
    */
    
    public class ExampleComboBoxEditorNOIndex  {
    
      public Component makeUI() {
        TheModel[] items = {
          new TheModel(true, true, "00000"),
          new TheModel(true, false, "11111"),
          new TheModel(false, true, "22222"),
          new TheModel(false, false, "33333")
        };
        JComboBox<TheModel> internalComboBox = new JComboBox<>();
        internalComboBox.setModel(new InternalComboBoxModel<>(items));
        internalComboBox.setEditable(true);
        internalComboBox.setEditor(new TheComboBoxEditor(internalComboBox.getFont()));
        internalComboBox.setRenderer(new TheComboBoxRenderer<>(internalComboBox.getFont()));
        internalComboBox.setMaximumRowCount(4);
    
        InternalComboBoxModel internalComboBoxModel  = (InternalComboBoxModel)internalComboBox.getModel();
        internalComboBox.addItemListener(e -> {
          if (e.getStateChange() == ItemEvent.SELECTED) {
            JComboBox combo = ((JComboBox) e.getSource());
            int lastValidIndex = combo.getSelectedIndex();
            if (lastValidIndex > -1) {
              internalComboBoxModel.setLastValidIndex(lastValidIndex);
              System.out.println("You chose " + combo.getSelectedItem() 
              + ", in position:" + lastValidIndex + "!");
            }
            combo.getEditor().selectAll();
          }
        });
    
        JPanel outer = new JPanel();
        outer.add(internalComboBox);
        outer.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
        return outer;
      }
    
      public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          f.getContentPane().add(new ExampleComboBoxEditorNOIndex().makeUI());
          f.setSize(320, 240);
          f.setLocationRelativeTo(null);
          f.setVisible(true);
        });
      }
    }
    
    class TheModel {
      private Boolean enabled = true;
      private Boolean defaultOperation = true;
      private String text = "";
      //public int index = -1;
    
      public TheModel(/*int idx, */Boolean enabled, Boolean defaultOperation, String text) {
        this.enabled = enabled;
        this.defaultOperation = defaultOperation;
        this.text = text;
        //this.index = idx;
      }
      public Boolean getEnabled() {
        return enabled;
      }
      public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
      }
      public Boolean getDefaultOperation() {
        return defaultOperation;
      }
      public void setDefaultOperation(Boolean defaultOperation) {
        this.defaultOperation = defaultOperation;
      }
      public String getText() {
        return text;
      }
      public void setText(String text) {
        this.text = text;
      }
      @Override
      public String toString() {
        return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation
          + ", text=" + text + '}';
      }
    }
    
    
    class TheComboBoxRenderer<E extends TheModel> implements ListCellRenderer<E> {
      protected ThePanel renderer;
      private int lastSelected = -1;
      public TheComboBoxRenderer(Font extFont) {
        renderer = new ThePanel(new TheModel(/*-1, */false, false, ""), extFont);
      }
      @Override
      public Component getListCellRendererComponent(JList<? extends E> list, E value,
          int index, boolean isSelected, boolean cellHasFocus) {
        if (isSelected) {
          this.lastSelected = index;
          //System.out.println("value: " + value + ", index: " + index + ", isSelected:" + isSelected);
        }
        renderer.setData(value);
        renderer.setBackground(isSelected ? new Color(200, 200, 255) : Color.WHITE);
        return renderer;
      }
    }
    
    class TheComboBoxEditor implements ComboBoxEditor {
      protected ThePanel editor;
      public TheComboBoxEditor(Font extFont) {
        super();
        editor = new ThePanel(new TheModel(/*-1, */false, false, ""), extFont);
        editor.setBorder(BorderFactory.createLineBorder(Color.GRAY));
      }
      @Override
      public void selectAll() {
        editor.selectAll();
        // editor.requestFocus(); // <-- The focus moves from jtfText to editor.
      }
      @Override
      public Object getItem() {
      //  System.out.println("getItem(): " + editor.getData());
        return editor.getData();
      }
      @Override
      public void setItem(Object anObject) {
      //  System.out.println("setItem: " + anObject);
        if (anObject instanceof TheModel) {
          TheModel d = (TheModel) anObject;
          editor.setData(d);
        } else {
          editor.setData(new TheModel(/*-1, */false, false, ""));
        }
      }
      @Override
      public Component getEditorComponent() {
        return editor;
      }
      @Override
      public void addActionListener(ActionListener l) {
      //  System.out.println("TheComboBoxEditor.addActionListener: " + l.getClass().getName());
        editor.addActionListener(l);
      }
      @Override
      public void removeActionListener(ActionListener l) {
      //  System.out.println("TheComboBoxEditor.removeActionListener: " + l.getClass().getName());
        editor.removeActionListener(l);
      }
    }
    
    
    class ThePanel extends JPanel {
      private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
      // Since there is no Unselected.png etc,
      // use JCheckBox instead of JToggleButton instead.
      public final JCheckBox jtbEnabled = new JCheckBox();
      public final JCheckBox jtbDefaultOperation = new JCheckBox();
      public final JTextField jtfText = new JTextField("", 10);
      private TheModel data;
    
      public ThePanel(TheModel data, Font extFont) {
        super();
        this.data = data;
        setData(data);
    
        jtbEnabled.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            if (combo.getItemCount() > 0) {
              InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
              int lastValidIndex = internalComboBoxModel.getLastValidIndex();
          //  TheModel o = (TheModel) combo.getSelectedItem();
          //  int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
              TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
              boolean b = ((JCheckBox) e.getSource()).isSelected();
              rd.setEnabled(b);
              jtbDefaultOperation.setEnabled(b);
            }
          }
        });
        jtbEnabled.setOpaque(false);
        jtbEnabled.setFocusable(false);
    
        jtbDefaultOperation.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            if (combo.getItemCount() > 0) {
              InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
              int lastValidIndex = internalComboBoxModel.getLastValidIndex();
          //  TheModel o = (TheModel) combo.getSelectedItem();
          //  int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
              TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
              rd.setDefaultOperation(((JCheckBox) e.getSource()).isSelected());
            }
          }
        });
        jtbDefaultOperation.setOpaque(false);
        jtbDefaultOperation.setFocusable(false);
    
        jtfText.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            if (combo.getItemCount() > 0) {
              InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
              int lastValidIndex = internalComboBoxModel.getLastValidIndex();
          //  TheModel o = (TheModel) combo.getSelectedItem();
          //  int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
              TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
              rd.setText(((JTextField) e.getSource()).getText());
            }
          }
        });
        jtfText.setBorder(BorderFactory.createEmptyBorder());
        jtfText.setOpaque(false);
    
        setOpaque(true);
        setBackground(Color.WHITE);
        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    
        add(Box.createRigidArea(new Dimension(2, 0)));
        add(jtbEnabled);
        add(jtbDefaultOperation);
        add(jtfText);
        add(Box.createRigidArea(new Dimension(2, 0)));
      }
    
      private <T> java.util.List<T> getComboBoxItems(JComboBox comboBox) {
        if (comboBox != null) {
          java.util.List<String> list = new ArrayList<>();
          for (int i = 0; i < comboBox.getItemCount(); i++) {
            list.add(comboBox.getItemAt(i).toString());
          }
          return (java.util.List<T>) list;//(ArrayList<T>)list; // list; // (List<T>)list;
        }
        return null;
      }
    
      private Integer positionItemList(java.util.List list, Object object) {
        Integer position = -1;
        Integer last = list.size();
        for (int pos = 0; pos < last; pos++) {
          if (list.get(pos).toString().equals(object.toString())) {
            position = pos;
          }
        }
        return position;
      }
    
      public TheModel getData() {
        return new TheModel(
            //data.index,
            jtbEnabled.isSelected(),
            jtbDefaultOperation.isSelected(),
            jtfText.getText());
      }
    
      public void setData(TheModel data) {
        //this.data.index = data.index;
        jtbEnabled.setSelected(data.getEnabled());
        jtbDefaultOperation.setEnabled(data.getEnabled());
        jtbDefaultOperation.setSelected(data.getDefaultOperation());
        jtfText.setText(data.getText());
      }
      public void selectAll() {
          jtfText.requestFocusInWindow();
          jtfText.selectAll();
      }
      public void addActionListener(ActionListener l) {
    
        jtfText.addActionListener(l);
        jtbEnabled.addActionListener(l);
        jtbDefaultOperation.addActionListener(l);
      }
      public void removeActionListener(ActionListener l) {
        jtfText.removeActionListener(l);
        jtbEnabled.removeActionListener(l);
        jtbDefaultOperation.removeActionListener(l);
      }
    
    }
    
    class InternalComboBoxModel<E extends TheModel> extends DefaultComboBoxModel {
      private Integer lastValidIndex = 0;
    
      InternalComboBoxModel(final E items[]) {
        super(items);
      }
    
      InternalComboBoxModel(Vector<E> v) {
        super(v);
      }
    
      public Integer getLastValidIndex() {
        return lastValidIndex;
      }
    
      public void setLastValidIndex(Integer lastValidIndex) {
        this.lastValidIndex = lastValidIndex;
      }
    
    }
    

    如果可能的话,我想解决所有的警告。

    MacBook-Air:Users bz$ javac -Xlint:unchecked -Xlint:deprecation -encoding utf8 -d /Users/bz/Documentos/Java/classes /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java
    /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:24: warning: [unchecked] unchecked method invocation: method setModel in class JComboBox is applied to given types
        internalComboBox.setModel(new InternalComboBoxModel<>(items));
                                 ^
      required: ComboBoxModel<E>
      found: InternalComboBoxModel<TheModel>
      where E is a type-variable:
        E extends Object declared in class JComboBox
    /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:24: warning: [unchecked] unchecked conversion
        internalComboBox.setModel(new InternalComboBoxModel<>(items));
                                  ^
      required: ComboBoxModel<E>
      found:    InternalComboBoxModel<TheModel>
      where E is a type-variable:
        E extends Object declared in class JComboBox
    /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:257: warning: [unchecked] unchecked cast
          return (java.util.List<T>) list;//(ArrayList<T>)list; // list; // (List<T>)list;
                                     ^
      required: List<T>
      found:    List<String>
      where T is a type-variable:
        T extends Object declared in method <T>getComboBoxItems(JComboBox)
    /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:310: warning: [unchecked] unchecked call to DefaultComboBoxModel(E[]) as a member of the raw type DefaultComboBoxModel
        super(items);
             ^
      where E is a type-variable:
        E extends Object declared in class DefaultComboBoxModel
    /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:314: warning: [unchecked] unchecked call to DefaultComboBoxModel(Vector<E>) as a member of the raw type DefaultComboBoxModel
        super(v);
             ^
      where E is a type-variable:
        E extends Object declared in class DefaultComboBoxModel
    5 warnings
    MacBook-Air:Users bz$ 
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   aterai    6 年前

    显示列表

    您需要添加一个单元渲染器。

    internalComboBox.setRenderer(new TheComboBoxRenderer<>(font));
    

    允许编辑

    editor.jtbDefaultOperation.addActionListener(e -> {
      System.out.println("jtbDefaultOperation" + editor.getData().index);
      Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, editor);
      if (c instanceof JComboBox) {
        JComboBox<?> combo = (JComboBox<?>) c;
        TheModel o = (TheModel) combo.getItemAt(editor.getData().index);
        o.setDefaultOperation(((JCheckBox) e.getSource()).isSelected());
      }
    });
    

    不要将焦点移到通讯盒编辑器上。

    internalComboBox.addItemListener(e -> {
      if (e.getStateChange() == ItemEvent.SELECTED) {
        System.out.println("You chose ...");
        ((JComboBox) e.getSource()).getEditor().selectAll();
      }
    });
    
    class TheComboBoxEditor implements ComboBoxEditor {
      @Override
      public void selectAll() {
        editor.selectAll();
        // editor.requestFocus(); // <-- The focus moves from JTextField(jtfText) to JPanel(ThePanel).
      }
    

    示例ComboBoxEditor3.java

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class ExampleComboBoxEditor3 {
      public Component makeUI() {
        TheModel[] items = {
          new TheModel(0, true, true, "00000"),
          new TheModel(1, true, false, "11111"),
          new TheModel(2, false, true, "22222"),
          new TheModel(3, false, false, "33333")
        };
        JComboBox<TheModel> internalComboBox = new JComboBox<>(items);
        internalComboBox.setEditable(true);
        internalComboBox.setEditor(new TheComboBoxEditor(internalComboBox.getFont()));
        internalComboBox.setRenderer(new TheComboBoxRenderer<>(internalComboBox.getFont()));
        internalComboBox.setMaximumRowCount(4);
        // internalComboBox.addActionListener(e -> {
        //   System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
        // });
        internalComboBox.addItemListener(e -> {
          if (e.getStateChange() == ItemEvent.SELECTED) {
            System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
            ((JComboBox) e.getSource()).getEditor().selectAll();
          }
        });
    
        JPanel outer = new JPanel();
        outer.add(internalComboBox);
        outer.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
        return outer;
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          f.getContentPane().add(new ExampleComboBoxEditor3().makeUI());
          f.setSize(320, 240);
          f.setLocationRelativeTo(null);
          f.setVisible(true);
        });
      }
    }
    
    class TheModel {
      private Boolean enabled = true;
      private Boolean defaultOperation = true;
      private String text = "";
      public int index = -1;
    
      public TheModel(int idx, Boolean enabled, Boolean defaultOperation, String text) {
        this.enabled = enabled;
        this.defaultOperation = defaultOperation;
        this.text = text;
        this.index = idx;
      }
      public Boolean getEnabled() {
        return enabled;
      }
      public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
      }
      public Boolean getDefaultOperation() {
        return defaultOperation;
      }
      public void setDefaultOperation(Boolean defaultOperation) {
        this.defaultOperation = defaultOperation;
      }
      public String getText() {
        return text;
      }
      public void setText(String text) {
        this.text = text;
      }
      @Override
      public String toString() {
        return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation
          + ", text=" + text + '}';
      }
    }
    
    class TheComboBoxRenderer<E extends TheModel> implements ListCellRenderer<E> {
      protected ThePanel renderer;
      public TheComboBoxRenderer(Font extFont) {
        renderer = new ThePanel(new TheModel(-1, false, false, ""), extFont);
      }
      @Override
      public Component getListCellRendererComponent(JList<? extends E> list, E value,
          int index, boolean isSelected, boolean cellHasFocus) {
        renderer.setData(value);
        renderer.setBackground(isSelected ? new Color(200, 200, 255) : Color.WHITE);
        return renderer;
      }
    }
    
    class TheComboBoxEditor implements ComboBoxEditor {
      protected ThePanel editor;
      public TheComboBoxEditor(Font extFont) {
        super();
        editor = new ThePanel(new TheModel(-1, false, false, ""), extFont);
        editor.setBorder(BorderFactory.createLineBorder(Color.GRAY));
      }
      @Override
      public void selectAll() {
        editor.selectAll();
        // editor.requestFocus(); // <-- The focus moves from jtfText to editor.
      }
      @Override
      public Object getItem() {
        return editor.getData();
      }
      @Override
      public void setItem(Object anObject) {
        if (anObject instanceof TheModel) {
          TheModel d = (TheModel) anObject;
          editor.setData(d);
        } else {
          editor.setData(new TheModel(-1, false, false, ""));
        }
      }
      @Override
      public Component getEditorComponent() {
        return editor;
      }
      @Override
      public void addActionListener(ActionListener l) {
        System.out.println("addActionListener: " + l.getClass().getName());
        editor.addActionListener(l);
      }
      @Override
      public void removeActionListener(ActionListener l) {
        System.out.println("removeActionListener: " + l.getClass().getName());
        editor.removeActionListener(l);
      }
    }
    
    class ThePanel extends JPanel {
      private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
      // Since there is no Unselected.png etc,
      // use JCheckBox instead of JToggleButton instead.
      public final JCheckBox jtbEnabled = new JCheckBox();
      public final JCheckBox jtbDefaultOperation = new JCheckBox();
      public final JTextField jtfText = new JTextField("", 10);
      private TheModel data;
    
      public ThePanel(TheModel data, Font extFont) {
        super();
        this.data = data;
        setData(data);
    
        jtbEnabled.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(data.index);
            boolean b = ((JCheckBox) e.getSource()).isSelected();
            o.setEnabled(b);
            jtbDefaultOperation.setEnabled(b);
          }
        });
        jtbEnabled.setOpaque(false);
        jtbEnabled.setFocusable(false);
    
        jtbDefaultOperation.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(data.index);
            o.setDefaultOperation(((JCheckBox) e.getSource()).isSelected());
          }
        });
        jtbDefaultOperation.setOpaque(false);
        jtbDefaultOperation.setFocusable(false);
    
        jtfText.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(data.index);
            o.setText(((JTextField) e.getSource()).getText());
          }
        });
        jtfText.setBorder(BorderFactory.createEmptyBorder());
        jtfText.setOpaque(false);
    
        setOpaque(true);
        setBackground(Color.WHITE);
        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    
        add(Box.createRigidArea(new Dimension(2, 0)));
        add(jtbEnabled);
        add(jtbDefaultOperation);
        add(jtfText);
        add(Box.createRigidArea(new Dimension(2, 0)));
      }
    
      public TheModel getData() {
        return new TheModel(
            data.index,
            jtbEnabled.isSelected(),
            jtbDefaultOperation.isSelected(),
            jtfText.getText());
      }
    
      public void setData(TheModel data) {
        this.data.index = data.index;
        jtbEnabled.setSelected(data.getEnabled());
        jtbDefaultOperation.setEnabled(data.getEnabled());
        jtbDefaultOperation.setSelected(data.getDefaultOperation());
        jtfText.setText(data.getText());
      }
      public void selectAll() {
          jtfText.requestFocusInWindow();
          jtfText.selectAll();
      }
      public void addActionListener(ActionListener l) {
        jtfText.addActionListener(l);
        jtbEnabled.addActionListener(l);
        jtbDefaultOperation.addActionListener(l);
      }
      public void removeActionListener(ActionListener l) {
        jtfText.removeActionListener(l);
        jtbEnabled.removeActionListener(l);
        jtbDefaultOperation.removeActionListener(l);
      }
    }
    

    示例comboboxeditor4.java

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class ExampleComboBoxEditor4 {
      public Component makeUI() {
        TheModel[] items = {
          new TheModel(true, true, "00000"),
          new TheModel(true, false, "11111"),
          new TheModel(false, true, "22222"),
          new TheModel(false, false, "33333")
        };
        JComboBox<TheModel> internalComboBox = new JComboBox<>(items);
        internalComboBox.setEditable(true);
        internalComboBox.setEditor(new TheComboBoxEditor(internalComboBox.getFont()));
        internalComboBox.setRenderer(new TheComboBoxRenderer<>(internalComboBox.getFont()));
        internalComboBox.setMaximumRowCount(4);
        // internalComboBox.addActionListener(e -> {
        //   System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
        // });
        internalComboBox.addItemListener(e -> {
          if (e.getStateChange() == ItemEvent.SELECTED) {
            System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
            ((JComboBox) e.getSource()).getEditor().selectAll();
          }
        });
    
        JPanel outer = new JPanel();
        outer.add(internalComboBox);
        outer.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
        return outer;
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          f.getContentPane().add(new ExampleComboBoxEditor4().makeUI());
          f.setSize(320, 240);
          f.setLocationRelativeTo(null);
          f.setVisible(true);
        });
      }
    }
    
    class TheModel {
      private Boolean enabled = true;
      private Boolean defaultOperation = true;
      private String text = "";
    
      public TheModel(Boolean enabled, Boolean defaultOperation, String text) {
        this.enabled = enabled;
        this.defaultOperation = defaultOperation;
        this.text = text;
      }
      public Boolean getEnabled() {
        return enabled;
      }
      public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
      }
      public Boolean getDefaultOperation() {
        return defaultOperation;
      }
      public void setDefaultOperation(Boolean defaultOperation) {
        this.defaultOperation = defaultOperation;
      }
      public String getText() {
        return text;
      }
      public void setText(String text) {
        this.text = text;
      }
      @Override
      public String toString() {
        return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation
          + ", text=" + text + '}';
      }
    //   // TEST:
    //   @Override
    //   public boolean equals(Object obj) {
    //     if (obj instanceof TheModel) {
    //       return Objects.equals(text, ((TheModel) obj).getText());
    //     } else {
    //       return false;
    //     }
    //   }
    }
    
    class TheComboBoxRenderer<E extends TheModel> implements ListCellRenderer<E> {
      protected ThePanel renderer;
      public TheComboBoxRenderer(Font extFont) {
        renderer = new ThePanel(new TheModel(false, false, ""), extFont);
      }
      @Override
      public Component getListCellRendererComponent(JList<? extends E> list, E value,
          int index, boolean isSelected, boolean cellHasFocus) {
        renderer.setData(value);
        renderer.setBackground(isSelected ? new Color(200, 200, 255) : Color.WHITE);
        return renderer;
      }
    }
    
    class TheComboBoxEditor implements ComboBoxEditor {
      protected ThePanel editor;
      public TheComboBoxEditor(Font extFont) {
        super();
        editor = new ThePanel(new TheModel(false, false, ""), extFont);
        editor.setBorder(BorderFactory.createLineBorder(Color.GRAY));
      }
      @Override
      public void selectAll() {
        editor.selectAll();
        // editor.requestFocus(); // <-- The focus moves from jtfText to editor.
      }
      @Override
      public Object getItem() {
        return editor.getData();
      }
      @Override
      public void setItem(Object anObject) {
        EventQueue.invokeLater(() -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, getEditorComponent());
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            int idx = combo.getSelectedIndex();
            if (idx >= 0 && idx != editor.lastValidIndex) {
              System.out.println("setItem: " + idx);
              editor.lastValidIndex = idx;
            }
          }
        });
        if (anObject instanceof TheModel) {
          TheModel d = (TheModel) anObject;
          editor.setData(d);
        } else {
          editor.setData(new TheModel(false, false, ""));
        }
      }
      @Override
      public Component getEditorComponent() {
        return editor;
      }
      @Override
      public void addActionListener(ActionListener l) {
        editor.addActionListener(l);
      }
      @Override
      public void removeActionListener(ActionListener l) {
        editor.removeActionListener(l);
      }
    }
    
    class ThePanel extends JPanel {
      private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
      // Since there is no Unselected.png etc,
      // use JCheckBox instead of JToggleButton instead.
      public final JCheckBox jtbEnabled = new JCheckBox();
      public final JCheckBox jtbDefaultOperation = new JCheckBox();
      public final JTextField jtfText = new JTextField("", 10);
      private TheModel data;
      public int lastValidIndex = -1;
    
      public ThePanel(TheModel data, Font extFont) {
        super();
        this.data = data;
        setData(data);
    
        jtbEnabled.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(lastValidIndex);
            boolean b = ((JCheckBox) e.getSource()).isSelected();
            o.setEnabled(b);
            jtbDefaultOperation.setEnabled(b);
            combo.setSelectedIndex(lastValidIndex);
          }
        });
        jtbEnabled.setOpaque(false);
        jtbEnabled.setFocusable(false);
    
        jtbDefaultOperation.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(lastValidIndex);
            o.setDefaultOperation(((JCheckBox) e.getSource()).isSelected());
            combo.setSelectedIndex(lastValidIndex);
          }
        });
        jtbDefaultOperation.setOpaque(false);
        jtbDefaultOperation.setFocusable(false);
    
        jtfText.addActionListener(e -> {
          Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
          if (c instanceof JComboBox) {
            JComboBox<?> combo = (JComboBox<?>) c;
            TheModel o = (TheModel) combo.getItemAt(lastValidIndex);
            o.setText(((JTextField) e.getSource()).getText());
            combo.setSelectedIndex(lastValidIndex);
          }
        });
        jtfText.setBorder(BorderFactory.createEmptyBorder());
        jtfText.setOpaque(false);
    
        setOpaque(true);
        setBackground(Color.WHITE);
        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    
        add(Box.createRigidArea(new Dimension(2, 0)));
        add(jtbEnabled);
        add(jtbDefaultOperation);
        add(jtfText);
        add(Box.createRigidArea(new Dimension(2, 0)));
      }
    
      public TheModel getData() {
        return new TheModel(
            jtbEnabled.isSelected(),
            jtbDefaultOperation.isSelected(),
            jtfText.getText());
      }
    
      public void setData(TheModel data) {
        jtbEnabled.setSelected(data.getEnabled());
        jtbDefaultOperation.setEnabled(data.getEnabled());
        jtbDefaultOperation.setSelected(data.getDefaultOperation());
        jtfText.setText(data.getText());
      }
      public void selectAll() {
        jtfText.requestFocusInWindow();
        jtfText.selectAll();
      }
      public void addActionListener(ActionListener l) {
        jtfText.addActionListener(l);
        jtbEnabled.addActionListener(l);
        jtbDefaultOperation.addActionListener(l);
      }
      public void removeActionListener(ActionListener l) {
        jtfText.removeActionListener(l);
        jtbEnabled.removeActionListener(l);
        jtbDefaultOperation.removeActionListener(l);
      }
    }