Question

I try to make an editable JComboBox with no arrow button. (It will show its dropdown list depending on what the user enters in its editor)

So far, the arrow button is not visible, but still clickable! And it still display the list on click.

public class MyComboBox<E> extends JComboBox<E> {

    public MyComboBox(E[] list) {
        super(list);
        this.setEditable(true);
        setUI(new BasicComboBoxUI() {
            @Override
            protected JButton createArrowButton() {
                return new JButton() {
                    @Override
                    public int getWidth() {
                        return 0;
                    }
                };
            }
        });
    }
}

Is there a way to disable it?

Was it helpful?

Solution

I finally succeed! the trick is that the ComboBox does not have the same components after changing the UI :

when listing the components before setUI method call :

class javax.swing.plaf.metal.MetalComboBoxButton

class javax.swing.CellRendererPane

class javax.swing.plaf.metal.MetalComboBoxEditor$1

when listing the components after setUI method call :

class kcomponent.MyComboBox$1$1

class javax.swing.plaf.basic.BasicComboBoxEditor$BorderlessTextField

class javax.swing.CellRendererPane

I then came to remove MouseListeners of these components and it worked on the second MouseListener of the first component : MyComboBox$1$1. But the cursor was still different (mouse pointer instead of a carret positioner), then I removed it entirely and it finally worked great!

Here is my corrected code :

public class MyComboBox<E> extends JComboBox<E> {

    public MyComboBox(E[] list) {
        super(list);
        this.setEditable(true);
        this.setUI(new BasicComboBoxUI() {
            @Override
            protected JButton createArrowButton() {
                return new JButton() {
                    @Override
                    public int getWidth() {
                        return 0;
                    }
                };
            }
        });
        this.remove(this.getComponent(0));
    }
}

OTHER TIPS

You could remove it if desired:

import java.awt.Component;
import java.awt.Container;

import javax.swing.AbstractButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;

public class PlayWithComboArrow {
   public static void main(String[] args) {
      String[] items = {"Fe", "Fi", "Fo", "Fum"};
      JComboBox<String> combo = new JComboBox<String>(items);
      combo.setEditable(true);

      removeButton(combo);

      JOptionPane.showMessageDialog(null, combo);
   }

   private static void removeButton(Container container) {
      Component[] components = container.getComponents();
      for (Component component : components) {
         if (component instanceof AbstractButton) {
            container.remove(component);
         }
      }
   }
}

Maybe you can use:

  • UIManager.put("ComboBox.squareButton", Boolean.FALSE);
  • JButton#setBorder(BorderFactory.createEmptyBorder());
  • JButton#setVisible(false);

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxUI;

public final class DisableArrowButtonTest {
  public JComponent makeUI() {
    String[] items = {
      "JComboBox 111111111:", "JComboBox 222:", "JComboBox 33:"
    };
    JComboBox<String> comboBox0 = new JComboBox<>(items);
    JComboBox<String> comboBox1 = new MyComboBox1<>(items);
    JComboBox<String> comboBox2 = new MyComboBox2<>(items);
    comboBox0.setEditable(true);
    comboBox1.setEditable(true);
    comboBox2.setEditable(true);

    JPanel p = new JPanel();
    p.add(comboBox0);
    p.add(Box.createRigidArea(new Dimension(300, 40)));
    p.add(comboBox1);
    p.add(Box.createRigidArea(new Dimension(300, 40)));
    p.add(comboBox2);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new DisableArrowButtonTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class MyComboBox1<E> extends JComboBox<E> {
  public MyComboBox1(E[] list) {
    super(list);
  }
  @Override public void updateUI() {
    super.updateUI();
    setUI(new BasicComboBoxUI() {
      @Override protected JButton createArrowButton() {
        return new JButton() {
          @Override public int getWidth() {
            return 0;
          }
        };
      }
    });
    setBorder(BorderFactory.createLineBorder(Color.GRAY));
  }
}

class MyComboBox2<E> extends JComboBox<E> {
  public MyComboBox2(E[] list) {
    super(list);
  }
  @Override public void updateUI() {
    super.updateUI();
    UIManager.put("ComboBox.squareButton", Boolean.FALSE);
    setUI(new BasicComboBoxUI() {
      @Override protected JButton createArrowButton() {
        JButton b = new JButton();
        b.setBorder(BorderFactory.createEmptyBorder());
        b.setVisible(false);
        return b;
      }
    });
    setBorder(BorderFactory.createLineBorder(Color.GRAY));
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top