Swing/DropDownHeightResizing の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/DropDownHeightResizing へ行く。
- Swing/DropDownHeightResizing の差分を削除
--- category: swing folder: DropDownHeightResizing title: JComboBoxのドロップダウンリストの高さをマウスドラッグで変更する tags: [JComboBox, JList, JPopupMenu] author: aterai pubdate: 2022-06-20T00:37:46+09:00 description: JComboBoxのドロップダウンリスト下部にドラッグ可能なアイコンを追加し、その高さをマウスドラッグで変更します。 image: https://drive.google.com/uc?id=1UN09ThQIcw2H8XpxI6ZpY2HOzFytr1-J hreflang: href: https://java-swing-tips.blogspot.com/2022/06/change-height-of-drop-down-list-of.html lang: en --- * 概要 [#summary] `JComboBox`のドロップダウンリスト下部にドラッグ可能なアイコンを追加し、その高さをマウスドラッグで変更します。 #download(https://drive.google.com/uc?id=1UN09ThQIcw2H8XpxI6ZpY2HOzFytr1-J) * サンプルコード [#sourcecode] #code(link){{ JPopupMenu popup = new JPopupMenu(); popup.setBorder(BorderFactory.createEmptyBorder()); popup.setPopupSize(240, 120); JLabel bottom = new JLabel("", new DotIcon(), SwingConstants.CENTER); MouseInputListener rwl = new ResizeWindowListener(popup); bottom.addMouseListener(rwl); bottom.addMouseMotionListener(rwl); bottom.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); bottom.setOpaque(true); bottom.setBackground(new Color(0xE0_E0_E0)); bottom.setFocusable(false); JPanel resizePanel = new JPanel(new BorderLayout()); resizePanel.add(scroll); resizePanel.add(bottom, BorderLayout.SOUTH); resizePanel.add(Box.createHorizontalStrut(240), BorderLayout.NORTH); resizePanel.setBorder(BorderFactory.createLineBorder(new Color(0x64_64_64))); JPopupMenu popup = new JPopupMenu(); popup.add(resizePanel); }} * 解説 [#explanation] - `JPopupMenu` -- `JPopupMenu`内に`JMenuItem`ではなく`BorderLayout`を設定した`JPanel`をひとつ配置 --- この`JPanel`は`BorderLayout.CENTER`に`JList`、`BorderLayout.SOUTH`に自身の親フレームの高さのみリサイズ可能にする`MouseInputListener`を設定した`JLabel`を追加 #code{{ class ResizeWindowListener extends MouseInputAdapter { class ResizePopupMenuListener extends MouseInputAdapter { private final Rectangle rect = new Rectangle(); private final JPopupMenu popup; private final Point startPt = new Point(); private final Dimension startDim = new Dimension(); protected ResizeWindowListener(JPopupMenu popup) { this.popup = popup; } @Override public void mousePressed(MouseEvent e) { Container popup = SwingUtilities.getAncestorOfClass( JPopupMenu.class, e.getComponent()); rect.setSize(popup.getSize()); startDim.setSize(popup.getSize()); startPt.setLocation(e.getComponent().getLocationOnScreen()); } @Override public void mouseDragged(MouseEvent e) { rect.height = startDim.height + e.getLocationOnScreen().y - startPt.y; popup.setPreferredSize(rect.getSize()); Window w = SwingUtilities.getWindowAncestor(popup); if (w != null && w.getType() == Window.Type.POPUP) { // Popup$HeavyWeightWindow w.setSize(rect.width, rect.height); } else { // Popup$LightWeightWindow popup.pack(); Container c = SwingUtilities.getAncestorOfClass( JPopupMenu.class, e.getComponent()); if (c instanceof JPopupMenu) { JPopupMenu popup = (JPopupMenu) c; popup.setPreferredSize(rect.getSize()); Window w = SwingUtilities.getWindowAncestor(popup); if (w != null && w.getType() == Window.Type.POPUP) { // Popup$HeavyWeightWindow w.setSize(rect.width, rect.height); } else { // Popup$LightWeightWindow popup.pack(); } } } } }} - `JComboBox` -- `JComboBox`本来のドロップダウンリストは`JComboBox.setMaximumRowCount(1)`で高さ最小、`JComboBox#getPreferredSize()`をオーバーライドして幅が上記の`JPopupMenu`以下になるよう設定し、`PopupMenuListener#popupMenuWillBecomeVisible(...)`で`JPopupMenu`を手前に重ねて表示 -- %%手前に表示する`JPopupMenu`は`Invoker`を`JComboBox`ではなく`null`に設定しているので`SwingUtilities.getWindowAncestor(JLabel)`で`JPopupMenu`の親フレームが取得可能%% --- %%`Invoker`を`JComboBox`に設定すると`JComboBox`の親フレームが返ってきてしまう%% -- %%`Invoker`が`null`なので`JComboBox`の親フレームをクリックしたりリサイズしても`JPopupMenu`は自動的に非表示にはならない%% --- %%このサンプルではその親フレームに`ComponentListener`などを追加して`JPopupMenu`を非表示に変更している%% -- `Invoker`を`JComboBox`に設定 --- `JPopupMenu`が親フレーム領域内に収まって`light weight popup`(`JPopupMenu#getTopLevelAncestor()`で`JComboBox`の親フレームが返ってくる)になる場合は`JPopupMenu#setPreferredSize(...) + JPopupMenu#pack()`でリサイズ --- `JPopupMenu`が親フレーム領域外に高さが拡大されて`heavy weight popup`(`JPopupMenu#getTopLevelAncestor()`で共用の`JWindow`が返ってくる)になる場合は`JPopupMenu#setPreferredSize(...) + JWindow#setSize(...)`でリサイズ - `JList` -- 手前に表示する`JPopupMenu`に追加した`JList`のアイテム選択と`JComboBox`のドロップダウンリストの選択状態を`ItemListener`を追加して同期 -- `JList`に`MouseListener`を追加してダブルクリックで`JComboBox`の選択状態更新と`JPopupMenu`の非表示化を実行 -- `GraphicsEnvironment#getAllFonts()`で取得したフォント名を一覧表示 * 参考リンク [#reference] - [[JToggleButtonからポップアップメニューを開く>Swing/ToolButtonPopup]] - [[JWindow内にフォーカス可能なコンポーネントを配置する>Swing/JWindowFocus]] - [[JComboBoxのドロップダウンリストでセル配置をニュースペーパー・スタイルに設定する>Swing/HorizontalWrapComboPopup]] - [[Fontの一覧を取得する>Swing/AllFonts]] * コメント [#comment] #comment #comment