向子菜单添加可滚动菜单

问题描述

我正试图适应子菜单https://coderanch.com/t/343946/java/Scrolling-JMenu中的代码,以便具有滚动条而不是像Java: Creating a scrolling submenu的答案中所建议的按钮。但是我在获得“标准”行为时遇到了一些麻烦:

  1. 当鼠标聚焦/悬停在可滚动菜单上时,父菜单不应消失(请参见“字体”菜单)。
  2. 当鼠标未聚焦/悬停在其或其父子菜单上时,可滚动菜单应消失(请参见“字体”菜单)。
  3. 即使子菜单的文本很长,滚动菜单也不应该消失(请参阅“帮助”菜单)。

在此先感谢您的帮助。这是我的代码

import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.jpopupmenu;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;

public class ScrollingMenu extends JFrame {

    private final jpopupmenu fontNameMenu = new jpopupmenu();
    private final JMenu[] fontMenuArray = new JMenu[] {new JMenu("Font Name"),new JMenu("Font Style")};
    private JMenu menu = new JMenu("Font");
    private final JMenu[] helpMenuArray = new JMenu[] {new JMenu("Very very very very very very very long Font Name Menu")};
    private JMenu hmenu = new JMenu("Help");
    
    public static void main(String[] args) {
        JFrame scrollingMenu = new ScrollingMenu();
        scrollingMenu.setVisible(true);
    }

    public ScrollingMenu() {
        
        // Creating a long array
        String[] systemFontArray = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        JCheckBoxMenuItem[] fontNameArray = new JCheckBoxMenuItem[systemFontArray.length];
        
        // Creating the scrollable menu
        GridBagLayout fontNameLayout=new GridBagLayout();
        JPanel fontNamePanel = new JPanel();
        fontNamePanel.setLayout(fontNameLayout);
        for (int i=0;i<systemFontArray.length;i++) {
            fontNameArray[i] = new JCheckBoxMenuItem(systemFontArray[i]);
            fontNameLayout.setConstraints(fontNameArray[i],new GridBagConstraints(0,i,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0),0));
            fontNamePanel.add(fontNameArray[i]);
        }
        JScrollPane fontScrollPane = new JScrollPane(fontNamePanel,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        this.fontNameMenu.add(fontScrollPane);

        // Adding the scrollable menu to a submenu
        addML(ScrollingMenu.this.fontMenuArray[0],ScrollingMenu.this.fontNameMenu,new Dimension(200,200));
        
        // Creating the Font Style submenu (for underlining problem 2)
        this.fontMenuArray[1].add(new JCheckBoxMenuItem("Bold"));
        this.fontMenuArray[1].add(new JCheckBoxMenuItem("Italic"));
        this.fontMenuArray[1].add(new JCheckBoxMenuItem("Plain"));
        
        // Adding the submenus to the Font menu
        for (int i=0;i<this.fontMenuArray.length;i++) {
            this.menu.add(this.fontMenuArray[i]);
        }
        
        // Adding the scrollable menu to a long text submenu (problem 3)
        addML(ScrollingMenu.this.helpMenuArray[0],200));
        
        // Adding the submenu to the Help menu
        for (int i=0;i<this.helpMenuArray.length;i++) {
            this.hmenu.add(this.helpMenuArray[i]);
        }
        
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(this.menu);
        menuBar.add(this.hmenu);
        this.setJMenuBar(menuBar);
        this.setDefaultCloSEOperation(disPOSE_ON_CLOSE);
        this.pack();
        this.setLocationRelativeto(null);
    }

    private static void addML (JMenu subMenu,jpopupmenu popupMenu,Dimension dimension) {
        popupMenu.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent focusEvent) {
                if(popupMenu.isVisible() && !subMenu.isSelected())
                    popupMenu.setVisible(false);
            }
        });
        popupMenu.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseExited(MouseEvent mouseEvent) {
                if(!subMenu.isSelected())
                    popupMenu.setVisible(false);
            }
        });
        popupMenu.setInvoker(subMenu);
        popupMenu.setPreferredSize(dimension);
        subMenu.addMouseListener(new MouseAdapter() {
            @Override
            public void mousepressed(MouseEvent mouseEvent) {
                if(!popupMenu.isVisible())
                    displayFontNameMenu(subMenu,popupMenu);
                else
                    popupMenu.setVisible(false);
            }
           @Override
            public void mouseEntered(MouseEvent mouseEvent) {
                if(!popupMenu.isVisible() && subMenu.isSelected())
                    displayFontNameMenu(subMenu,popupMenu);
            }
           @Override
            public void mouseExited(MouseEvent mouseEvent) {
                if(popupMenu.isVisible() && !popupMenu.contains(mouseEvent.getPoint())) {
                    popupMenu.setVisible(false);
                }
            }
        });
    }

    private static void displayFontNameMenu(JMenu subMenu,jpopupmenu popupMenu) {
        Rectangle rectangle = subMenu.getBounds();
        Point point = new Point(rectangle.x  +rectangle.width,rectangle.y);
        SwingUtilities.convertPointToScreen(point,subMenu.getParent());
        popupMenu.setLocation(point.x,point.y);
        popupMenu.setVisible(true);
    }

}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)