Swing/SplitButton の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/SplitButton へ行く。
- Swing/SplitButton の差分を削除
--- category: swing folder: SplitButton title: JComboBoxのドロップダウンリストで異なる高さのセルを使用する tags: [JComboBox, JList, ListCellRenderer, PopupMenuListener, JTextArea] author: aterai pubdate: 2024-09-30T08:53:40+09:00 description: JComboBoxのセルレンダラとして選択状態用のJCheckBox、複数行文字列用のJTextAreaなどを配置したJPanelを使用し、異なる高さのセルを描画します。 image: https://drive.google.com/uc?id=1tSfYI71idR4Y2i-iH0OxQHtBwLjQghGk --- * 概要 [#summary] JComboBoxのセルレンダラとして選択状態用のJCheckBox、複数行文字列用のJTextAreaなどを配置したJPanelを使用し、異なる高さのセルを描画します。 `JComboBox`のセルレンダラとして選択状態用の`JCheckBox`、複数行文字列用の`JTextArea`などを配置した`JPanel`を使用し、異なる高さのセルを描画します。 #download(https://drive.google.com/uc?id=1tSfYI71idR4Y2i-iH0OxQHtBwLjQghGk) * サンプルコード [#sourcecode] #code(link){{ 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); } }; }} * 解説 [#explanation] - `JComboBox#setPrototypeCellValue(...)`で`JComboBox`本体のサイズを指定 -- ドロップダウンリストで使用する`JList`のセルサイズには影響せず(自動的に`JList#setPrototypeCellValue(...)`は実行されない)、デフォルトの`JList.setFixedCellHeight(-1)`が適用されて各要素のセルレンダラに`getPreferredSize`を設定して`ListUI`でセルの高さが計算される -- [[JListで異なる高さのセルを使用>Swing/DifferentCellHeight]] - `JComboBox`に`PopupMenuListener`を追加してドロップダウンリストの幅を`JComboBox`本体より広く設定 -- [[JComboBoxのドロップダウンリスト幅を指定値以上に保つ>Swing/ComboPopupWidth]] - `JComboBox#setRenderer(...)`で`ListCellRenderer#getListCellRendererComponent(...)`を実装したセルレンダラを設定 -- ドロップダウンリストのセルを描画する場合(`index>=0`)は、選択状態を表示する`JCheckBox`、タイトルを表示する`JLabel`、複数行のテキストを表示する`JTextArea`などを`JPanel`に配置して返す -- `JComboBox`本体のセルを描画する場合(`index==-1`)は、タイトルを表示する`JLabel`を返す #code{{ 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; } } }} * 参考リンク [#reference] - [[JListで異なる高さのセルを使用>Swing/DifferentCellHeight]] - [[JComboBoxのドロップダウンリスト幅を指定値以上に保つ>Swing/ComboPopupWidth]] - [https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request Merging a pull request - GitHub Docs] -- via: [https://azukiazusa.dev/blog/customizable-select-element/ スタイルをカスタマイズ可能な新しい `<select>` 要素] * コメント [#comment] #comment #comment