OK, here it is. To keep things simple, only the combo box is subclassed. This means a small kludge is necessary but saves a lot of faffing around.

Note that it recalculates the popup width every time it gets popped up, which might be slow for huge lists of items. You could tweak it to only calculate the popup width when a new item is added, and use the precalculated value in the getsize() method instead. Also, it uses a kludge value in the calculateOptimumPopupWidth() method to compensate for the popup insets that are subtracted from the width in the popup's caller method (BasicComboPopup.getPopupLocation()). You could use the actual popup inset values here, but you'd have to supply a custom UI to give you access to the popup, which isn't directly accessible from the combo box (who designed this thing?):
Code:
public class AutoComboBox extends JComboBox {
    private boolean layingOut;
    private boolean isAutoPopupWidth = true;
    private int popupWidth;

    public AutoComboBox(Vector items) {
        super(items);
    }

    public AutoComboBox(ArrayList items) {
        this(items.toArray());
    }

    public AutoComboBox(ComboBoxModel comboBoxModel) {
        super(comboBoxModel);
    }

    public AutoComboBox(Object[] items) {
        super(items);
    }

    /**
     * Overriden to handle the popup Size
     */
    public void doLayout() {
        try {
            layingOut = true;
            super.doLayout();
        }
        finally {
            layingOut = false;
        }
    }

    /**
     * Overriden to handle the popup Size
     */
    public Dimension getSize() {
        Dimension dim = super.getSize();
        if (!layingOut) {
            if (isAutoPopupWidth) {
                popupWidth = getOptimumPopupWidth();
            }
            if (popupWidth != 0) {
                dim.width = popupWidth;
            }
        }
        return dim;
    }

    // return the greater of the combo width and the optimum popup width.
    private int getOptimumPopupWidth() {
        return Math.max(super.getSize().width, calculateOptimumPopupWidth());
    }

    // Find the maximum item text width
    private int calculateOptimumPopupWidth() {
        int width = 0;
        FontMetrics fontMetrics = getFontMetrics(getFont());
        for (int i = 0; i < getItemCount(); i++) {
            String text = getItemAt(i).toString();
            width = Math.max(width, fontMetrics.stringWidth(text));
        }
        // kludge to allow for BasicComboPopup insets (default 1 left + 1 right) which are subtracted from the
        // returned width (see BasicComboPopup.getPopupLocation()).
        return width + 3;
    }

    /**
     * Set the popup width to be the optimum (as for setOptimumPopupWidth) before displaying it.
     *
     * @param autoPopupWidth true to set the optimum width, false for the default behaviour.
     */
    public void setAutoPopupWidth(boolean autoPopupWidth) {
        isAutoPopupWidth = autoPopupWidth;
        if (!autoPopupWidth) {
            popupWidth = 0;
        }
    }

    /**
     * Indicates whether the popup width is automatically optimised before display.
     *
     * @return true if the popup width is automatically optimised, false if not.
     */
    public boolean isAutoPopupWidth() {
        return isAutoPopupWidth;
    }
}
The problem is never how to get new, innovative thoughts into your mind, but how to get old ones out!
D. Hock