Swing/ScrollableListMenu のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ScrollableListMenu へ行く。
- 1 (2025-02-24 (月) 01:26:49)
- 2 (2025-02-24 (月) 21:10:36)
- category: swing folder: ScrollableListMenu title: JMenuのJPopupMenuにスクロール可能なJListを配置する tags: [JMenu, JPopupMenu, JScrollPane, JList] author: aterai pubdate: 2025-02-24T01:23:27+09:00 description: JMenuのJPopupMenuにJMenuItemではなくスクロールや選択が可能なJListを使用します。 image: https://drive.google.com/uc?id=1fc4sYPBKTHGjJz8rlWWdInMAthSUFFV4
Summary
JMenuのJPopupMenuにJMenuItemではなくスクロールや選択が可能なJListを使用します。
Screenshot

Advertisement
Source Code Examples
Font[] fonts = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAllFonts();
DefaultListModel<String> model = new DefaultListModel<>();
Stream.of(fonts)
.map(Font::getFontName)
.sorted()
.forEach(model::addElement);
JList<String> list = new PopupList<>(model);
JScrollPane scroll = new JScrollPane(list);
scroll.setBorder(BorderFactory.createEmptyBorder());
scroll.setViewportBorder(BorderFactory.createEmptyBorder());
JMenu subMenu = new JMenu("Font list");
subMenu.add(scroll);
// ...
class PopupList<E> extends JList<E> {
private transient PopupListMouseListener listener;
protected PopupList(ListModel<E> model) {
super(model);
}
@Override public void updateUI() {
removeMouseListener(listener);
removeMouseMotionListener(listener);
super.updateUI();
setFixedCellHeight(20);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listener = new PopupListMouseListener();
addMouseListener(listener);
addMouseMotionListener(listener);
Color selectedBg = new Color(0x91_C9_F7);
ListCellRenderer<? super E> renderer = getCellRenderer();
setCellRenderer((list, value, index, isSelected, cellHasFocus) -> {
Component c = renderer.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
if (c instanceof JComponent && listener.isRolloverIndex(index)) {
c.setBackground(selectedBg);
c.setForeground(Color.WHITE);
}
return c;
});
}
}
View in GitHub: Java, KotlinExplanation
JMenu#add(scrollPane)
でJMenu
が使用するJPopupMenu
の末尾にJMenuItem
ではなくJScrollPane
でスクロール可能にしたJList
を配置JPopupMenu
に配置されたJList
はスクロール可能だが、マウスカーソルでのロールオーバーやマウスクリックでの選択が不可になるので、以下のようなMouseAdapter
を追加して対応- `mouseMoved(...)`が実行されたらロールオーバー表示するリストアイテムのインデックスを記憶し、`JList`に設定した`ListCellRenderer`で背景色などを変更 - `mouseClicked(...)`が実行されたら`MenuSelectionManager.defaultManager().clearSelectedPath();`を実行することですべてのメニューを閉じる
class PopupListMouseListener extends MouseAdapter {
private int index = -1;
public boolean isRolloverIndex(int i) {
return this.index == i;
}
private void setRollover(MouseEvent e) {
Point pt = e.getPoint();
Component c = e.getComponent();
if (c instanceof JList) {
index = ((JList<?>) c).locationToIndex(pt);
c.repaint();
}
}
@Override public void mouseMoved(MouseEvent e) {
setRollover(e);
}
@Override public void mouseDragged(MouseEvent e) {
setRollover(e);
}
@Override public void mouseClicked(MouseEvent e) {
MenuSelectionManager.defaultManager().clearSelectedPath();
}
@Override public void mouseExited(MouseEvent e) {
index = -1;
e.getComponent().repaint();
}
}