JComboBoxのドロップダウンリストでセル配置をニュースペーパー・スタイルに設定する
Total: 1971
, Today: 1
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
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;
}