发生的情况是组合的内部尝试动态地找到首选大小。为此,它遍历列表中的所有项目,将项目提供给渲染器以测量渲染组件的首选大小。
您可以通过设置原型值进行测量来防止这种情况,然后使用该原型测量一次尺寸
comboBox.setPrototypeDisplayValue(sampleFont);
编辑:正如@Boro 检测到的那样,这还不够——它只为组合框本身设置原型,而不是为弹出窗口中的列表设置原型(应该如此,这可能有多疯狂)。要破解,我们必须手动设置它,这是一个可以使用的代码片段
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(略有更改,期望字体类型的项目)
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;
}
}