Что происходит, так это то, что внутренности комбо пытаются динамически найти предпочтительный размер. Для этого он перебирает все элементы в списке, передает в средство визуализации элементы для измерения предпочтительного размера компонента визуализации.
Вы можете предотвратить это, установив prototypeValue для измерения, затем размер измеряется один раз с использованием этого прототипа
comboBox.setPrototypeDisplayValue(sampleFont);
Редактировать: как обнаружил @Boro, этого недостаточно - он устанавливает прототип только для самого comboBox, а не для списка во всплывающем окне (как и должно быть, насколько безумно глючит это ... возможно). Чтобы взломать, мы должны установить его вручную, вот фрагмент кода для игры с
public class ComboWithPrototype {
private JComponent createContent() {
final Font[] systemFonts = GraphicsEnvironment
.getLocalGraphicsEnvironment().getAllFonts();
final JComboBox box = new JComboBox();
box.setRenderer(new ComboBoxRenderer());
box.setPrototypeDisplayValue(systemFonts[0]);
Accessible a = box.getUI().getAccessibleChild(box, 0);
if (a instanceof javax.swing.plaf.basic.ComboPopup) {
JList popupList = ((javax.swing.plaf.basic.ComboPopup) a).getList();
// route the comboBox' prototype to the list
// should happen in BasicComboxBoxUI
popupList.setPrototypeCellValue(box.getPrototypeDisplayValue());
}
Action action = new AbstractAction("set model") {
@Override
public void actionPerformed(ActionEvent e) {
box.setModel(new DefaultComboBoxModel(systemFonts));
}
};
JComponent panel = new JPanel(new BorderLayout());
panel.add(box);
panel.add(new JButton(action), BorderLayout.SOUTH);
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ComboWithPrototype().createContent());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
});
}
Пользовательский ListCellRenderer (слегка изменен, чтобы ожидать элементы типа Font)
private class ComboBoxRenderer extends DefaultListCellRenderer {
private Font baseFont = new JLabel("Test").getFont();
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
if (value instanceof Font) {
Font font = (Font) value;
setFont(new Font(font.getName(), baseFont.getStyle(), baseFont.getSize()));
setText(font.getName());
}
return this;
}
}