AccessibleJMenu 中的 AccessibleSelection 在鼠标更改 JMenu 后返回

The AccessibleSelection in a AccessibleJMenu is returning after the mouse changes JMenu

问题底部的代码为我需要单击 JMenu 的相当具体的情况提供了解决方案,它应该像 JButton 一样工作,同时保持几乎所有JMenu 的格式。 ActionMenuJMenu 之间的格式差异应该是在单击后,它应该 return 到其正常状态(见图)。

使用当前代码,它可以做到这一点。然而;如果您要将鼠标移到不同的菜单上,或者如果您将鼠标 down/up 移出菜单然后将鼠标悬停在它上面,菜单将进入其选定状态(见图)。这不应该发生。

我的问题是为什么在 AccessibleSelection 被清除并且 PopupMenu 被设置为不可见之后会发生这种情况?

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;

public class Main extends JFrame {
    private static final long serialVersionUID = 3206847208968227199L;

    private Main() {
        setSize(600, 600);
        setJMenuBar(new MenuBar());
        setVisible(true);
        setLocationRelativeTo(null);
    }

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

    private class MenuBar extends JMenuBar {
        private static final long serialVersionUID = -2055260049565317972L;

        MenuBar() {
            add(new ActionMenu("Menu"));
            add(new JMenu("Another Menu"));
        }
    }

    private class ActionMenu extends JMenu {
        private static final long serialVersionUID = -6885806048559452542L;

        public ActionMenu(String name) {
            setText(name);
            menuItem();
        }

        JButton butInvis;

        private void menuItem() {
            butInvis = new JButton();
            butInvis.addActionListener(new MenuActionListener());
            addMouseListener(new MenuMouseListener());
        }

        private class MenuMouseListener extends MouseAdapter {
            public void mouseClicked(MouseEvent e) {
                clcikComponent(butInvis);
            }

            private void clcikComponent(JButton comp) {
                comp.doClick();
            }
        }

        private class MenuActionListener implements ActionListener {
            public void actionPerformed(ActionEvent e)  {
                AccessibleJMenu aJ = (AccessibleJMenu) getAccessibleContext();
                aJ.clearAccessibleSelection();
                getPopupMenu().setVisible(false);
            }
        }
    }
}

编辑
我忘了说原来我是在 JMenu 上用 setSelected(false) 做的(见下面的代码);但是,当您将鼠标悬停在另一个 JMenu.

上时,这会导致完全相同的问题
private class MenuActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        setSelected(false);
    }
}

要解决此问题,您需要使用 JMenuBarAccessibleContext 而不是 JMenu。这可以用代码行完成

getParent().getAccessibleContext().getAccessibleSelection().clearAccessibleSelection();

在这个例子中,代码将放在 MenuActionListener 中,它看起来像下面的代码。

private class MenuActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        getParent().getAccessibleContext().getAccessibleSelection().clearAccessibleSelection();
    }
}

Andrew Thompson, this should not be done because of the Principle of Least Astonishment 所述,除非您要更改组件的格式(本例中为 Action Menu),使其看起来不像另一个组件。