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
概要
JComboBox
のドロップダウンリストに配置されるJList
のセルレイアウト方法をニュースペーパー・スタイルに変更します。
Screenshot
Advertisement
サンプルコード
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());
}
};
}
View in GitHub: Java, Kotlin解説
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
)だけ高くなっている
- デフォルトセルレンダラーの
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;
}