将JScrollPane添加到JMenu

3

我有一个 JMenu,其中将包含从数据库生成的 JMenuItem。因此,很可能菜单过大而超出屏幕。

因此,我正在尝试将 JScrollPane 添加到 JMenu 中。

例如,类似于:

JMenu employeesMenu = new JMenu("Employees");
JScrollPane emScroll = new JScrollPane();
JList contents = new JList();

contents.add(new JRadioButton("1"));
contents.add(new JRadioButton("2"));
contents.add(new JRadioButton("3"));
// ... etc

emScroll.add(contents);
employeesMenu.add(emScroll);

现在,我了解到一个 JMenu 的内容存储在一个 JPopupMenu 中的一个 JList 中。那么我的问题是,有什么方法可以将该 JList 强制放入 JScrollPane 中呢?另外,是否可以使用 JScrollBar 替代?任何输入将不胜感激。

我想知道这是否可能? - Ron
@Ron E - 我已经看了一些内容,似乎是可以的,但之前类似问题的回答并不全面,我无法自己弄清楚。 - Rudi Kershaw
也许涉及到 JMenu.add(Component c) 和添加 JScrollPane? - Ron
尝试一下这个:http://www.java2s.com/Tutorial/Java/0240__Swing/CreatingCustomMenuElementComponentsTheMenuElementInterface.htm - René Link
@RenéLink - 你所说的“this”,是指在自定义的JScrollPane上实现MenuElement接口吗? - Rudi Kershaw
2个回答

2
也许你可以使用Darryl的菜单滚动方法。它会在需要时在菜单顶部/底部添加箭头按钮。

Darryl的菜单滚动条对于这个特定的解决方案来说并不是特别可行,因为在某些菜单中,可能会有许多按字母顺序排列的条目,实际的滚动条会使生活变得更加轻松。 - Rudi Kershaw
@RudiKershaw 菜单不适合用于数百个条目,您可能需要重新考虑您的用户界面。既然如此:您可能需要自己实现一个定制解决方案(或者雇用顾问为您完成它 :-) - kleopatra
1
@kleopatra - 我已经通过使用JComboBox解决了这个问题,但我会保持问题的开放性,因为我认为它值得有一个答案。我正在考虑将其作为业余项目,并创建自己的自定义JPopupMenu类。如果在回答之前我完成了这个项目,我会为其他人发布结果。至于菜单不适用于数百个项目,这可能是正确的,但Excel在其过滤器中使用菜单项样式PopupMenus,这非常有效。 - Rudi Kershaw
1
@RudiKershaw 好的,期待您的解决方案 :-) - kleopatra

1
下面展示了如何将JScrollPane添加到JMenu中。在下面的菜单项中使用了JLabel组件,因为似乎无法在JScrollPane中使用JMenuItem。为了模仿JMenuItem的行为,即在鼠标进入/退出时更改颜色,并在单击项目时执行操作(在本例中,打印出标签的文本,可用于决定接下来的操作),每个JLabel都添加了一个mouseListener。根据需要,可能需要调整scrollPane.setPreferredSize以及鼠标进入/退出项时的颜色(即使为方便起见,当前LookAndFeel用于JMenuItem的默认颜色也被使用)。
JLabel文本中使用<html>标签的原因是允许背景颜色(当您将鼠标移动到项目上时)填充JScrollPane中每个项目的宽度,而不仅仅是应用背景颜色到文本结束的位置。在读取所选项目/标签的文本时,会删除<html>标签。 MenuExample.java
import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class MenuExample {
    Random rand = new Random();
    Color menuBackCol;
    Color mItemBackCol;
    Color mItemForegCol;
    Color mItmSelBackCol;
    Color mItmSelForegCol;

    MenuExample() {
        menuBackCol = UIManager.getColor("Menu.background");
        mItemBackCol = UIManager.getColor("MenuItem.background");
        mItemForegCol = UIManager.getColor("MenuItem.foreground");
        mItmSelBackCol = UIManager.getColor("MenuItem.selectionBackground");
        mItmSelForegCol = UIManager.getColor("MenuItem.selectionForeground");

        Box box = new Box(BoxLayout.Y_AXIS);

        for (int i = 0; i < 250; i++) {
            box.add(Box.createRigidArea(new Dimension(0, 2))); // creates space between the components
            JLabel lbl = new JLabel("<html> &ensp;" + i + ": " + rand.nextInt(10000) + "</html>");
            lbl.setOpaque(true);
            lbl.setBackground(mItemBackCol);
            lbl.addMouseListener(
                    new LabelController(lbl, mItemBackCol, mItemForegCol, mItmSelBackCol, mItmSelForegCol));
            box.add(lbl);
        }

        JScrollPane scrollPane = new JScrollPane(box);
        scrollPane.getVerticalScrollBar().setUnitIncrement(20); // adjusts scrolling speed
        scrollPane.setPreferredSize(new Dimension(100, 300));
        scrollPane.setBorder(BorderFactory.createEmptyBorder());
        scrollPane.getViewport().setBackground(menuBackCol);

        JMenuBar mb = new JMenuBar();
        JMenu menu = new JMenu("Menu");
        JMenu submenu = new JMenu("Sub Menu");
        submenu.add(scrollPane);
        menu.add(new JMenuItem("Item 1"));
        menu.add(new JMenuItem("Item 2"));
        menu.add(new JMenuItem("Item 3"));
        menu.add(submenu);
        mb.add(menu);

        JFrame f = new JFrame("Menu with ScrollBar Example");
        f.setJMenuBar(mb);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(640, 480);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String args[]) {
        new MenuExample();
    }
}

LabelController.java

import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class LabelController implements MouseListener {

    JLabel lbl;
    Color mItemBackCol;
    Color mItemForegCol;
    Color mItmSelBackCol;
    Color mItmSelForegCol;

    public LabelController(JLabel lbl, Color mItemBackCol, Color mItemForegCol, Color mItmSelBackCol,
            Color mItmSelForegCol) {
        this.lbl = lbl;
        this.mItemBackCol = mItemBackCol;
        this.mItemForegCol = mItemForegCol;
        this.mItmSelBackCol = mItmSelBackCol;
        this.mItmSelForegCol = mItmSelForegCol;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        String selectedText = lbl.getText().replaceAll("<[^>]*>", "").replace("&ensp;","").trim();
        System.out.println(selectedText);
        javax.swing.MenuSelectionManager.defaultManager().clearSelectedPath(); // close the menu
        lbl.setBackground(mItemBackCol);
        lbl.setForeground(mItemForegCol);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        lbl.setBackground(mItmSelBackCol);
        lbl.setForeground(mItmSelForegCol);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        lbl.setBackground(mItemBackCol);
        lbl.setForeground(mItemForegCol);
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接