以下是从我的实时应用程序中获取的完整工作答案:
我解决鼠标退出菜单关闭的方法是在构造函数的顶部运行一个布尔变量“isMouseOut”来跟踪,然后以更OO友好的方式分配MouseListener来跟踪多个MouseIn-MouseOut事件当用户与菜单交互时。它调用了一个单独的 menuClear 方法,作用于布尔“isMouseOut”的状态。该类实现 MouseListener。这就是它的完成方式。
首先创建一个 ArrayList,将所有菜单项添加到该数组中。像这样:
Font menuFont = new Font("Arial", Font.PLAIN, 12);
JMenuBar menuBar = new JMenuBar();
getContentPane().add(menuBar, BorderLayout.NORTH);
// Array of MenuItems
ArrayList<JMenuItem> aMenuItms = new ArrayList<JMenuItem>();
JMenuItem mntmRefresh = new JMenuItem("Refresh");
JMenuItem mntmNew = new JMenuItem("New");
JMenuItem mntmNormal = new JMenuItem("Normal");
JMenuItem mntmMax = new JMenuItem("Max");
JMenuItem mntmStatus = new JMenuItem("Status");
JMenuItem mntmFeedback = new JMenuItem("Send Feedback");
JMenuItem mntmEtsyTWebsite = new JMenuItem("EtsyT website");
JMenuItem mntmAbout = new JMenuItem("About");
aMenuItms.add(mntmRefresh);
aMenuItms.add(mntmNew);
aMenuItms.add(mntmNormal);
aMenuItms.add(mntmMax);
aMenuItms.add(mntmStatus);
aMenuItms.add(mntmFeedback);
aMenuItms.add(mntmEtsyTWebsite);
aMenuItms.add(mntmAbout);
然后在此阶段迭代 arrayList,使用 for() 循环添加 MouseListener:
for (Component c : aMenuItms) {
if (c instanceof JMenuItem) {
c.addMouseListener(ml);
}
}
现在为 MenuBar 设置 JMenu 父级:
// Now set JMenu parents on MenuBar
final JMenu mnFile = new JMenu("File");
menuBar.add(mnFile).setFont(menuFont);
final JMenu mnView = new JMenu("View");
menuBar.add(mnView).setFont(menuFont);
final JMenu mnHelp = new JMenu("Help");
menuBar.add(mnHelp).setFont(menuFont);
然后将下拉 menuItems 子项添加到 JMenu 父项:
// Now set menuItems as children of JMenu parents
mnFile.add(mntmRefresh).setFont(menuFont);
mnFile.add(mntmNew).setFont(menuFont);
mnView.add(mntmNormal).setFont(menuFont);
mnView.add(mntmMax).setFont(menuFont);
mnHelp.add(mntmStatus).setFont(menuFont);
mnHelp.add(mntmFeedback).setFont(menuFont);
mnHelp.add(mntmEtsyTWebsite).setFont(menuFont);
mnHelp.add(mntmAbout).setFont(menuFont);
将 mouseListeners 作为单独的步骤添加到 JMenu 父级:
for (Component c : menuBar.getComponents()) {
if (c instanceof JMenu) {
c.addMouseListener(ml);
}
}
现在,子 menuItem 元素都有自己的侦听器,这些侦听器与父 JMenu 元素和 MenuBar 本身是分开的 - 在 MouseListener() 实例化中识别对象类型很重要,这样您就可以在鼠标悬停时自动打开菜单(在这个例子是 3x JMenu 父母)但也避免了子异常错误,并允许在不尝试监视鼠标位置的情况下干净地识别菜单结构的 mouseOUT。鼠标监听器如下:
MouseListener ml = new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
isMouseOut = true;
timerMenuClear();
}
public void mouseEntered(MouseEvent e) {
isMouseOut = false;
Object eSource = e.getSource();
if(eSource == mnHelp || eSource == mnView || eSource == mnFile){
((JMenu) eSource).doClick();
}
}
};
以上仅模拟鼠标单击 JMenu 'parents'(本例中为 3x),因为它们是子菜单下拉菜单的触发器。timerMenuClear() 方法调用 MenuSelectionManager 以清空在真正 mouseOUT 时处于活动状态的任何选定路径点:
public void timerMenuClear(){
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isMouseOut == true){
System.out.println("Timer");
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
};
//Delay timer half a second to ensure real mouseOUT
Timer timer = new Timer(1000, task);
timer.setInitialDelay(500);
timer.setRepeats(false);
timer.start();
}
我花了一些时间进行测试,监控在开发过程中我可以在 JVM 中访问哪些值 - 但它确实是一种享受!即使有嵌套菜单 :) 我希望很多人发现这个完整的例子非常有用。