Вот хак, который я придумал.Недостатки:
- Если вы хотите сохранить внешний вид и внешний вид, вы должны отдельно разделить на подклассы каждое расширение
BasicComboBoxUI
, о котором вы заботитесь - , вам нужно использовать отражение для загрузкиКлассы пользовательского интерфейса, поскольку (например) подкласс
WindowsComboBoxUI
не будет загружаться в Linux - , он не будет работать с L & F (например, MacOS?), Которые не расширяются
BasicComboBoxUI
- он делает предположения о
ListCellRenderer
, который не всегда может быть оправдан
Я все еще открыт для более чистых решений.
class FastBasicComboBoxUI extends BasicComboBoxUI {
@Override
public void installUI(JComponent c) {
super.installUI(c);
Object prototypeValue = this.comboBox.getPrototypeDisplayValue();
if (prototypeValue != null) {
ListCellRenderer renderer = comboBox.getRenderer();
Component rendererComponent = renderer
.getListCellRendererComponent(this.listBox,
prototypeValue, 0, false, false);
if (rendererComponent instanceof JLabel) {
// Preferred size of the renderer itself is (-1,-1) at this point,
// so we need this hack
Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
.getText()).getPreferredSize();
this.listBox.setFixedCellHeight(prototypeSize.height);
this.listBox.setFixedCellWidth(prototypeSize.width);
}
}
}
}
Я все еще открыт для чистыхРешения.
Позже
Оказывается, это решило только некоторые проблемы.Начальное отображение поля со списком с большим количеством элементов может быть очень медленным.Я должен был убедиться, что всплывающий список немедленно получает фиксированный размер ячейки, перемещая код в саму ComboPopup
, как показано ниже.Обратите внимание, что, как указано выше, это зависит от значения прототипа.
@Override
protected ComboPopup createPopup() {
return new BasicComboPopup(comboBox) {
@Override
protected JList createList() {
JList list = super.createList();
Object prototypeValue = comboBox.getPrototypeDisplayValue();
if (prototypeValue != null) {
ListCellRenderer renderer = comboBox.getRenderer();
Component rendererComponent = renderer
.getListCellRendererComponent(list, prototypeValue, 0, false, false);
if (rendererComponent instanceof JLabel) {
// Preferred size of the renderer itself is (-1,-1) at this point,
// so we need this hack
Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
.getText()).getPreferredSize();
list.setFixedCellHeight(prototypeSize.height);
list.setFixedCellWidth(prototypeSize.width);
}
}
return list;
}
};
}