Swing/HorizontalWrapComboPopup のバックアップ差分(No.3)
- バックアップ一覧
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/HorizontalWrapComboPopup へ行く。
- 1 (2020-03-23 (月) 18:55:15)
- 2 (2020-03-23 (月) 20:55:48)
- 3 (2020-08-31 (月) 14:33:35)
- 4 (2022-03-08 (火) 19:34:01)
- 追加された行はこの色です。
- 削除された行はこの色です。
---
category: swing
folder: HorizontalWrapComboPopup
title: JComboBoxのドロップダウンリストでセル配置をニュースペーパー・スタイルに設定する
tags: [JComboBox, JList, ComboPopup]
author: aterai
pubdate: 2020-03-23T18:45:14+09:00
description: JComboBoxのドロップダウンリストに配置されるJListのセルレイアウト方法をニュースペーパー・スタイルに変更します。
image: https://drive.google.com/uc?id=1LMv0w83y7RJ0-0V28KBL2DIppbJ9EM1P
---
* 概要 [#summary]
`JComboBox`のドロップダウンリストに配置される`JList`のセルレイアウト方法をニュースペーパー・スタイルに変更します。
#download(https://drive.google.com/uc?id=1LMv0w83y7RJ0-0V28KBL2DIppbJ9EM1P)
* サンプルコード [#sourcecode]
#code(link){{
private static JComboBox<Icon> makeComboBox1(ComboBoxModel<Icon> model, Icon proto) {
return new JComboBox<Icon>(model) {
@Override public Dimension getPreferredSize() {
Insets i = getInsets();
int w = proto.getIconWidth();
int h = proto.getIconHeight();
return new Dimension(w * 3 + i.left + i.right, h + i.top + i.bottom);
}
@Override public void updateUI() {
super.updateUI();
setMaximumRowCount(3);
setPrototypeDisplayValue(proto);
ComboPopup popup = (ComboPopup) getAccessibleContext().getAccessibleChild(0);
JList<?> list = popup.getList();
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(3);
list.setFixedCellWidth(proto.getIconWidth());
list.setFixedCellHeight(proto.getIconHeight());
}
};
}
}}
* 解説 [#explanation]
- `PreferredSize`
-- `JComboBox#getPreferredSize()`をオーバーライドして`JComboBox`の幅をセルサイズの`3`倍になるよう変更
-- `ComboPopup#getList()`でドロップダウンリストに配置される`JList`を取得してセルの配置方法を`HORIZONTAL_WRAP`に変更
--- `JList`の下側に余計な余白が生成されてしまう?
-- `JComboBox#setMaximumRowCount(3)`、`JList#setVisibleRowCount(3)`で`3`行のセルを表示するよう変更
--- 片方だけ設定するとスクロールバーが表示されたり、余計な余白ができる場合がある
-- `JComboBox#setPrototypeDisplayValue(...)`、`JList#setFixedCellWidth(...)`、`JList#setFixedCellHeight(...)`でセルサイズを変更
--- `JComboBox#setPrototypeDisplayValue(...)`のみ指定する場合、セルの右に余分な余白が生成される?
- `PopupMenuListener`
-- `JComboBox#getPreferredSize()`をオーバーライドして`JComboBox`の幅をセルサイズと矢印ボタンの合計になるよう変更
--- このサンプルで使用している矢印ボタンの幅は`20px`固定
-- `PopupMenuListener`を追加してドロップダウンリストを開く直前だけ`JComboBox`の幅をセルサイズの`3`倍になるよう変更
-- `JList`の下側に余計な余白が生成されてしまうことを防ぐため`ListCellRenderer`を変更
--- デフォルトセルレンダラーの`Border`余白の合計分(`(top:1 + bottom:1) * 行:3 = 6px`)だけ高くなっている
#code{{
private static JComboBox<Icon> makeComboBox2(ComboBoxModel<Icon> model, Icon proto) {
JComboBox<Icon> combo = new JComboBox<Icon>(model) {
@Override public Dimension getPreferredSize() {
Insets i = getInsets();
int w = proto.getIconWidth();
int h = proto.getIconHeight();
return new Dimension(20 + w + i.left + i.right, h + i.top + i.bottom);
}
@Override public void updateUI() {
setRenderer(null);
super.updateUI();
setMaximumRowCount(3);
setPrototypeDisplayValue(proto);
ListCellRenderer<? super Icon> r = getRenderer();
setRenderer((list, value, index, isSelected, cellHasFocus) -> {
Component c = r.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (c instanceof JLabel) {
JLabel l = (JLabel) c;
l.setIcon(value);
l.setBorder(BorderFactory.createEmptyBorder());
}
return c;
});
ComboPopup popup = (ComboPopup) getAccessibleContext().getAccessibleChild(0);
JList<?> list = popup.getList();
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(3);
list.setFixedCellWidth(proto.getIconWidth());
list.setFixedCellHeight(proto.getIconHeight());
}
};
combo.addPopupMenuListener(new PopupMenuListener() {
private boolean adjusting;
@Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
JComboBox<?> combo = (JComboBox<?>) e.getSource();
Insets i = combo.getInsets();
int popupWidth = proto.getIconWidth() * 3 + i.left + i.right;
Dimension size = combo.getSize();
if (size.width >= popupWidth) {
return;
}
if (!adjusting) {
adjusting = true;
combo.setSize(popupWidth, size.height);
combo.showPopup();
}
combo.setSize(size);
adjusting = false;
}
@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
/* not needed */
}
@Override public void popupMenuCanceled(PopupMenuEvent e) {
/* not needed */
}
});
return combo;
}
}}
* 参考リンク [#reference]
- [[JComboBoxのドロップダウンリスト幅を指定値以上に保つ>Swing/ComboPopupWidth]]
- [[JPopupMenuをボタンの長押しで表示>Swing/PressAndHoldButton]]
* コメント [#comment]
#comment
#comment