Getting the FontMetrics of all available fonts on your system?

This code will display some FontMetrics information about the font you select.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      FontRendering fr = new FontRendering();
      getContentPane().add(BorderLayout.CENTER, fr);
      getContentPane().add(BorderLayout.NORTH, new FontRenderingControls(fr));
   } 
 
   public static class FontRenderingControls extends JPanel implements ActionListener {
      FontRendering fr;
 
      public FontRenderingControls(FontRendering fr) {
         this.fr = fr;
 
         Vector v = new Vector();
         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
         Font f[] = ge.getAllFonts();
         for (int i = 0; i < f.length; i++) {
            if (f[i].canDisplayUpTo(f[i].getName()) > 0) {
               v.addElement(f[i].getName());
            }
         }      
 
         final JComboBox fontCombo = new JComboBox(v);
         add(fontCombo);
         fontCombo.addActionListener(this);
      }
 
      public void actionPerformed(ActionEvent e) {
         JComboBox fontCombo = (JComboBox) e.getSource();
         fr.font = (String) fontCombo.getSelectedItem();
         fr.repaint();
      }
   }
 
   public static class FontRendering extends JPanel {
      public String text = "Easter Island";
      public String font = "Helvetica";
 
      public void paint(Graphics g) {
         Graphics2D g2d = (Graphics2D) g;
 
         Font f = g2d.getFont();
  
         g2d.setFont(new Font(font, Font.BOLD, 36));
         g2d.drawString(text, 10, 40); 
 
         FontMetrics fm = g2d.getFontMetrics();
    
         g2d.setFont(f);
         FontMetrics fm2 = g2d.getFontMetrics();
         g2d.drawString("FontMetrics:", 10, 60);
         g2d.drawString("Ascent: "      + 
                          fm.getAscent(), 50, 60 + fm2.getHeight());
         g2d.drawString("Descent: "     + 
                          fm.getDescent(), 50, 60 + fm2.getHeight() * 2);
         g2d.drawString("Height: "      + 
                          fm.getHeight(), 50, 60 + fm2.getHeight() * 3);
         g2d.drawString("Leading: "     + 
                          fm.getLeading(), 50, 60 + fm2.getHeight() * 4);
         g2d.drawString("MaxAdvance: "  + 
                          fm.getMaxAdvance(), 50, 60 + fm2.getHeight() * 5);
         g2d.drawString("MaxAscent: "   + 
                          fm.getMaxAscent(), 50, 60 + fm2.getHeight() * 6);
         g2d.drawString("MaxDescent: "  + 
                          fm.getMaxDescent(), 50, 60 + fm2.getHeight() * 7);
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 300);
   }
}

Aligning the text in a JComboBox to the right

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      this.addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
      Object []items = new Object[] { "one", "two", "three", "four", 
                                      "five", "six", "seven" };
      JComboBox comboBox = new JComboBox(items);
      getContentPane().add(comboBox);
 
      DefaultListCellRenderer listRenderer = new DefaultListCellRenderer();
      listRenderer.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
      comboBox.setRenderer(listRenderer);      
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(200, 200);
      main.setVisible(true);
   }
}

Creating an auto-complete JComboBox

Main.java:

import javax.swing.plaf.basic.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
 
      String[] elements = new String[] { "arthur", "brian", "chet", "danny", "dave",  
                                         "don", "edmond", "eddy", "glen", "gregory", "john",
                                         "ken", "malcolm", "pete", "stephanie", "yvonne" };
 
      JComboBox comboBox = new AutoCompleteComboBox(elements);
      getContentPane().add(comboBox);
   }
      
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}
 
class AutoCompleteComboBox extends JComboBox
{
   public int caretPos=0;
   public JTextField inputField=null;
 
   public AutoCompleteComboBox(final Object elements[]) {
      super(elements);
      setEditor(new BasicComboBoxEditor());
      setEditable(true);
   }
 
   public void setSelectedIndex(int index) {
      super.setSelectedIndex(index);
 
      inputField.setText(getItemAt(index).toString());
      inputField.setSelectionEnd(caretPos + tf.getText().length());
      inputField.moveCaretPosition(caretPos);
   }
 
   public void setEditor(ComboBoxEditor editor) {
      super.setEditor(editor);
      if (editor.getEditorComponent() instanceof JTextField) {
         inputField = (JTextField) editor.getEditorComponent();
 
         inputField.addKeyListener(new KeyAdapter() {
            public void keyReleased( KeyEvent ev ) {
               char key=ev.getKeyChar();
               if (! (Character.isLetterOrDigit(key) || Character.isSpaceChar(key) )) return;
 
               caretPos=inputField.getCaretPosition();
               String text="";
               try {
                  text=inputField.getText(0, caretPos);
               }
               catch (javax.swing.text.BadLocationException e) {
                  e.printStackTrace();
               }
 
               for (int i=0; i<getItemCount(); i++) {
                  String element = (String) getItemAt(i);
                  if (element.startsWith(text)) {
                     setSelectedIndex(i);
                     return;
                  }
               }
            }
         });
      }
   }
}

Putting a JCheckbox in a JComboBox

Here’s a working example:

Main.java:

import javax.swing.*;
import java.awt.*;
import java.util.*;
 
public class Main extends JFrame
{
   public Main() {
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       
      getContentPane().setLayout(new FlowLayout());
       
      Vector v = new Vector();
      v.add("Europe");
      v.add(new JCheckBox("Brussels", false));
      v.add(new JCheckBox("Paris", false));
      v.add(new JCheckBox("London", false));
      v.add("United States");
      v.add(new JCheckBox("New York", false));
      v.add(new JCheckBox("Detroit", false));
      v.add(new JCheckBox("San Francisco", false));
 
      getContentPane().add(new JComboCheckBox(v));
   }
    
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

JComboCheckBox.java:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
 
public class JComboCheckBox extends JComboBox 
{
   public JComboCheckBox() { 
      init(); 
   }
   
   public JComboCheckBox(JCheckBox[] items) { 
      super(items); 
      init(); 
   }
   
   public JComboCheckBox(Vector items) { 
      super(items); 
      init(); 
   }
   
   public JComboCheckBox(ComboBoxModel aModel) { 
      super(aModel); 
      init(); 
   }
   
   private void init() {
      setRenderer(new ComboBoxRenderer());
      addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) { 
            itemSelected(); 
         }
      });
   }
 
   private void itemSelected() {
      if (getSelectedItem() instanceof JCheckBox) {
         JCheckBox jcb = (JCheckBox)getSelectedItem();
         jcb.setSelected(!jcb.isSelected());
      }
   }
 
   class ComboBoxRenderer implements ListCellRenderer {
      private JLabel label;
      
      public ComboBoxRenderer() { 
         setOpaque(true); 
      }
      
      public Component getListCellRendererComponent(JList list, Object value, int index, 
                                                    boolean isSelected, boolean cellHasFocus) {
         if (value instanceof Component) {
            Component c = (Component)value;
            if (isSelected) {
               c.setBackground(list.getSelectionBackground());
               c.setForeground(list.getSelectionForeground());
            } else {
               c.setBackground(list.getBackground());
               c.setForeground(list.getForeground());
            }
             
            return c;
         } else {
            if (label ==null) {
               label = new JLabel(value.toString());
            }
            else {
               label.setText(value.toString());
            }
               
            return label;
         }
      }
   }
}

Detecting a selection change on a JComboBox

Use an ActionListener.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame { 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
 
      Vector v = new Vector();
      v.add(&quot;first element&quot;);
      v.add(&quot;second element&quot;);
      v.add(&quot;third element&quot;);
      v.add(&quot;fourth element&quot;);
      v.add(&quot;fifth element&quot;);
 
      final JComboBox cb = new JComboBox(v);
      cb.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println(cb.getSelectedItem());
         }
      });
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
      getContentPane().add(new JLabel(&quot;Select element:&quot;));
      getContentPane().add(cb);
   } 
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Creating a JComboBox that doesn’t close when I click one of its JCheckBox items

Main.java:

import javax.swing.*;
import java.awt.*;
import java.util.*;
 
public class Main extends JFrame
{
   public Main() {
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       
      getContentPane().setLayout(new FlowLayout());
       
      Vector v = new Vector();
      v.add("Europe");
      v.add(new JCheckBox("Brussels", false));
      v.add(new JCheckBox("Paris", false));
      v.add(new JCheckBox("London", false));
      v.add("United States");
      v.add(new JCheckBox("New York", false));
      v.add(new JCheckBox("Detroit", false));
      v.add(new JCheckBox("San Francisco", false));
 
      getContentPane().add(new JComboCheckBox(v));
   }
    
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

JComboCheckBox.java:

import javax.swing.*;
import java.awt.event.*;
 
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.MetalComboBoxUI;
 
import com.sun.java.swing.plaf.motif.MotifComboBoxUI;
import com.sun.java.swing.plaf.windows.WindowsComboBoxUI;
 
import java.awt.*;
import java.util.*;
 
public class JComboCheckBox extends JComboBox 
{
   public JComboCheckBox() { 
      init(); 
   }
    
   public JComboCheckBox(JCheckBox[] items) { 
      super(items); 
      init(); 
   }
    
   public JComboCheckBox(Vector items) { 
      super(items); 
      init(); 
   }
    
   public JComboCheckBox(ComboBoxModel aModel) { 
      super(aModel); 
      init(); 
   }
    
   public void updateUI() {
      ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this);
      if (cui instanceof MetalComboBoxUI) {
         cui = new MetalNoCloseComboBoxUI();
      } else if (cui instanceof MotifComboBoxUI) {
         cui = new MotifNoCloseComboBoxUI();       
      } else if (cui instanceof WindowsComboBoxUI) {
         cui = new WindowsNoCloseComboBoxUI();
      }
       
      setUI(cui);
   }
    
   class MetalNoCloseComboBoxUI extends MetalComboBoxUI {
      protected ComboPopup createPopup() {
         return new NoCloseBasicComboPopup(comboBox);
      }
   }
 
   class WindowsNoCloseComboBoxUI extends WindowsComboBoxUI {
      protected ComboPopup createPopup() {
         return new NoCloseBasicComboPopup(comboBox);
      }
   }
 
   class MotifNoCloseComboBoxUI extends MotifComboBoxUI {
      protected ComboPopup createPopup() {
         return new NoCloseBasicComboPopup(comboBox);
      }
   }
    
   private void init() {
      setRenderer(new ComboBoxRenderer());
      addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) { 
            itemSelected(); 
         }
      });
   }
 
   private void itemSelected() {
      if (getSelectedItem() instanceof JCheckBox) {
         JCheckBox jcb = (JCheckBox)getSelectedItem();
         jcb.setSelected(!jcb.isSelected());
         repaint();
      }
   }
 
   class ComboBoxRenderer implements ListCellRenderer {
      private JLabel label;
      
      public ComboBoxRenderer() { 
         setOpaque(true); 
      }
      
      public Component getListCellRendererComponent(JList list, Object value, int index, 
                                                    boolean isSelected, boolean cellHasFocus) {
         if (value instanceof JCheckBox) {
            list.repaint();
         }
         if (value instanceof Component) {
            Component c = (Component)value;
            if (isSelected) {
               c.setBackground(list.getSelectionBackground());
               c.setForeground(list.getSelectionForeground());
            } else {
               c.setBackground(list.getBackground());
               c.setForeground(list.getForeground());
            }
            
            return c;
         } else {
            if (label==null) {
               label = new JLabel(value.toString());
            }
            else {
               label.setText(value.toString()); 
            }
            
            return label;
         }
      }
   }
 
   class NoCloseBasicComboPopup extends BasicComboPopup
   {
      public NoCloseBasicComboPopup(JComboBox combo) {
         super(combo);         
      }
   
      protected MouseListener createListMouseListener() {
         return new ListMouseHandler();
      }
   
      protected class ListMouseHandler extends MouseAdapter {
         public void mousePressed(MouseEvent e) {
         }
      
         public void mouseReleased(MouseEvent anEvent) {
            comboBox.setSelectedIndex(list.getSelectedIndex());
            Object o = list.getSelectedValue();
            if (! (o instanceof JCheckBox)) {
               hide();
            }
         }
      }   
   }   
}

Putting a JButton inside a JComboBox

Here’s an example:

import javax.swing.plaf.basic.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
    
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
      
      final JButton buttonOk = new JButton("OK");
      buttonOk.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println(ae.getActionCommand() + " clicked!");
         }
      });
      final JButton buttonCancel = new JButton("Cancel");
      buttonCancel.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println(ae.getActionCommand() + " clicked!");
         }
      });
 
      final JComboBox combobox = 
         new JComboBox(new Object[] {
               "Item 1",
               "Item 2",
               "Item 3",
               buttonOk,
               "Item 4",
               "Item 5",
               buttonCancel
            }
         );
 
      getContentPane().add(combobox);
      combobox.setRenderer(new ButtonComboBoxRenderer());
      combobox.addActionListener(new ButtonComboBoxListener(this, combobox));
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
   
      setSize(new Dimension(200, 200));
   } 
 
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}
 
class ButtonComboBoxRenderer extends BasicComboBoxRenderer implements ListCellRenderer
{
   public ButtonComboBoxRenderer() {
      super();
   }
   
   public Component getListCellRendererComponent( JList list, 
           Object value, int index, boolean isSelected, boolean cellHasFocus) {
      if (isSelected) {
          setBackground(list.getSelectionBackground());
          setForeground(list.getSelectionForeground());
      }
      else {
          setBackground(list.getBackground());
          setForeground(list.getForeground());
      }
 
      setFont(list.getFont());
      if (value instanceof Icon) {
         setIcon((Icon)value);
      }
      if (value instanceof JButton) {
         return (Component) value;
      }
      else {
         setText((value == null) ? "" : value.toString());
      }
 
      return this;
  }  
}
 
class ButtonComboBoxListener implements ActionListener {
   JComboBox combobox;
   JFrame frame;
 
   ButtonComboBoxListener(JFrame frame, JComboBox combobox) {
      this.frame = frame;
      this.combobox = combobox;
      combobox.setSelectedIndex(0);
   }
     
   public void actionPerformed(ActionEvent e) {
      Object selectedItem = combobox.getSelectedItem();
      if (selectedItem instanceof JButton) {
         ((JButton) selectedItem).doClick();
      }
   }
}

Invoking a JPopupMenu from a JComboBox

Add a MouseListener:

import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
    
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
      
      final JComboBox combobox = new JComboBox(new String[] { "Item 1", "Item 2", "Item 3" });
      final JPopupMenu popup = new JPopupMenu();
      JMenuItem mi1 = new JMenuItem("Popup Item 1");
      JMenuItem mi2 = new JMenuItem("Popup Item 2");
      popup.add(mi1);
      popup.add(mi2);
 
      ((JButton) combobox.getComponent(0)).addMouseListener(new MouseAdapter() {
         public void mousePressed(MouseEvent me) {
            if (me.isPopupTrigger()) {
               popup.show(combobox, me.getX(), me.getY());
            }
         }
 
         public void mouseReleased(MouseEvent me) {
            if (me.isPopupTrigger()) {
               popup.show(combobox, me.getX(), me.getY());
            }
         }
      });
 
      getContentPane().add(combobox);
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
   
      setSize(new Dimension(200, 200));
   } 
 
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}

Creating an editable JComboBox

Use the method setEditable. Here’s an example:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
   
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      final JComboBox combobox = new JComboBox();
      final JList list = new JList(new DefaultListModel());
 
      getContentPane().add(BorderLayout.NORTH, combobox);
      getContentPane().add(BorderLayout.CENTER, list); 
 
      combobox.setEditable(true);
      combobox.addItemListener(new ItemListener() {
         public void itemStateChanged(ItemEvent ie) {
            if (ie.getStateChange() == ItemEvent.SELECTED) {
               ((DefaultListModel) list.getModel()).addElement(combobox.getSelectedItem());
               combobox.insertItemAt(combobox.getSelectedItem(), 0);
            }
         }
      });
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
   
      setSize(new Dimension(200, 200));
   } 
 
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}

Showing a different tooltip for every item in a JComboBox

Modify the behavior of the ListRenderer such that it includes the currently selected JComboBox item in determining the tooltip text. Here’s an example:

import javax.swing.plaf.basic.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
    
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
      
      final JComboBox combobox = new JComboBox(new String[] { "Item 1", "Item 2", "Item 3" });
 
      getContentPane().add(combobox);
 
      combobox.setRenderer(new BasicComboBoxRenderer() {
         public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
            if (isSelected) { 
               setBackground(list.getSelectionBackground()); 
               setForeground(list.getSelectionForeground()); 
               if (index > -1) {
                  list.setToolTipText("Tooltip #" + new Integer(index).toString()); 
               }
            }
            else { 
               setBackground(list.getBackground()); 
               setForeground(list.getForeground()); 
            } 
            setFont(list.getFont()); 
            setText((value == null) ? "" : value.toString()); 
 
            return this; 
         }
      });
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
   
      setSize(new Dimension(200, 200));
   } 
 
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}