JComboBoxのドロップダウンリストで異なる高さのセルを使用する
Total: 107
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JComboBox
のセルレンダラとして選択状態用のJCheckBox
、複数行文字列用のJTextArea
などを配置したJPanel
を使用し、異なる高さのセルを描画します。
Screenshot
Advertisement
サンプルコード
JComboBox<ComboItem> combo = new JComboBox<ComboItem>(model) {
private transient PopupMenuListener listener;
@Override public void updateUI() {
removePopupMenuListener(listener);
super.updateUI();
setPrototypeDisplayValue(new ComboItem("**********", ""));
setRenderer(new CheckComboBoxRenderer<>(this));
// AccessibleContext ac = getAccessibleContext();
// ComboPopup popup = (ComboPopup) ac.getAccessibleChild(0);
// JList<?> list = popup.getList();
// list.setFixedCellHeight(-1);
listener = new WidePopupMenuListener();
addPopupMenuListener(listener);
}
};
View in GitHub: Java, Kotlin解説
JComboBox#setPrototypeCellValue(...)
でJComboBox
本体のサイズを指定- ドロップダウンリストで使用する
JList
のセルサイズには影響せず(自動的にJList#setPrototypeCellValue(...)
は実行されない)、デフォルトのJList.setFixedCellHeight(-1)
が適用されて各要素のセルレンダラにgetPreferredSize
を設定してListUI
でセルの高さが計算される - JListで異なる高さのセルを使用
- ドロップダウンリストで使用する
JComboBox
にPopupMenuListener
を追加してドロップダウンリストの幅をJComboBox
本体より広く設定JComboBox#setRenderer(...)
でListCellRenderer#getListCellRendererComponent(...)
を実装したセルレンダラを設定- ドロップダウンリストのセルを描画する場合(
index>=0
)は、選択状態を表示するJCheckBox
、タイトルを表示するJLabel
、複数行のテキストを表示するJTextArea
などをJPanel
に配置して返す JComboBox
本体のセルを描画する場合(index==-1
)は、タイトルを表示するJLabel
を返す
- ドロップダウンリストのセルを描画する場合(
class CheckComboBoxRenderer<E extends ComboItem>
implements ListCellRenderer<E> {
private static final Color SELECTED_BGC = new Color(0xC0_E8_FF);
private final EditorPanel renderer;
private final JLabel label = new JLabel();
private final JComboBox<ComboItem> combo;
protected CheckComboBoxRenderer(JComboBox<ComboItem> combo) {
this.combo = combo;
ComboItem proto = Optional
.ofNullable(combo.getPrototypeDisplayValue())
.orElseGet(() -> new ComboItem("", ""));
renderer = new EditorPanel(proto);
}
@Override public Component getListCellRendererComponent(
JList<? extends E> list, E value, int index,
boolean isSelected, boolean cellHasFocus) {
Component c;
if (index >= 0) {
renderer.setItem(value);
if (isSelected) {
renderer.setSelected(true);
renderer.setOpaque(true);
renderer.setBackground(SELECTED_BGC);
} else {
renderer.setSelected(combo.getSelectedIndex() == index);
renderer.setOpaque(false);
renderer.setBackground(Color.WHITE);
}
c = renderer;
} else {
label.setOpaque(false);
label.setText(Objects.toString(value, ""));
c = label;
}
return c;
}
}