これが私が思いついたハックです。欠点は次のとおりです。
- ルックアンドフィールを維持したい場合は、関心のある各
BasicComboBoxUI
拡張機能を個別にサブクラス化する必要があります
- (たとえば) のサブクラスは
WindowsComboBoxUI
Linux では読み込まれないため、リフレクションを使用して UI クラスを読み込む必要があります。
- 拡張しない 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;
}
};
}