2012-08-25 14 views
7

Die JMenuBar zeigt JMenuItem s nicht als ausgewählt an oder zeigt die JMenu Popups an, bis sie zum ersten Mal angeklickt werden. Nachdem Sie irgendwo in JMenuBar geklickt haben, reagieren alle diese Elemente auf Mouse-Hover.Aktivieren von JMenuBar bei Hover

Ich möchte den ersten erforderlichen Klick umgehen und es automatisch aktiviert haben, wenn Sie die Maus bewegen. Gibt es eine Möglichkeit, dies zu tun?

+3

Haben Sie einen guten Grund, warum Sie das tun möchten? Alle Menüleisten in allen Anwendungen verhalten sich so – Robin

+0

Gut mein Menü hat ein kundenspezifisches Aussehen und dieses Verhalten passt es natürlicher. Außerdem glaube ich, dass dieses Verhalten für den Benutzer viel interaktiver ist. – springcorn

Antwort

9

Der Weg ist, eine MouseListener auf der JMenu hinzuzufügen und auf Ereignisse mouseEntered zu hören. In den Ereignisbehandlungsroutinen müssen Sie nur auf doClick klicken. Beispiel:

jMenuFile.addMouseListener(new MouseListener(){ 
    public void mouseEntered(MouseEvent e) { 
     jMenuFile.doClick(); 
    } 
    ... 
}); 

Nach dem programmgesteuerten Klicken auf die Maus wird das Popup-Menü automatisch geöffnet. Um ein ganzes JMenuBar zu aktivieren, müssen Sie jedem JMenu einen Listener hinzufügen. Zu diesem Zweck ist es besser, ein Listener-Objekt separat zu erstellen.

Ich habe zwei Menüpunkte auf der Bar, also tat ich:

MouseListener ml = new MouseListener(){ 
    public void mouseClicked(MouseEvent e) {} 
    public void mousePressed(MouseEvent e) {} 
    public void mouseReleased(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) { 
     ((JMenu)e.getSource()).doClick(); 
    } 
    }; 
    jMenuFile.addMouseListener(ml); 
    jMenuHelp.addMouseListener(ml); 

Wenn Sie so viele Menüpunkte auf der Bar, können Sie es nur wiederholen:

for (Component c: jMenuBar1.getComponents()) { 
    if (c instanceof JMenu){ 
     c.addMouseListener(ml); 
    } 
} 
+0

Ich verstehe die MausEntered Listener, aber wie aktivieren Sie die gesamte JMenuBar von der MouseNentered? – springcorn

+0

soeben bearbeitet –

+0

Danke. Das brachte mich auf den richtigen Weg, aber ich habe gehofft, dass es einen einfacheren Weg gibt, dies zu tun, wie jMenuBar.activate(), anstatt den Klick einzeln zu erzwingen. Für JMenuItem können Sie doClick() nicht aufrufen, stattdessen glaube ich, dass der beste Weg, um dieses Verhalten zu erzeugen, setArmed (true) ist – springcorn

1

Roman Cs erste und akzeptierte Antwort wird nicht AUTO Schließen Sie das Menü mit untergeordneten MenuItems als Teil der JMenuBar.

Ausführen einer ((JMenu) e.getSource()). DoClick(); mousEntered simuliert den Klick in einen der JMenu-Eltern, kann aber nicht einfach zur mouseExited-Methode hinzugefügt werden, da der MouseListener sowohl an die untergeordneten MenuItems als auch an die JMenu-Eltern angehängt werden muss. (Was es in der normalen Zuordnung zur MenuBar nicht tut - nur an die übergeordneten JMenu-Objekte anfügen).

Außerdem tritt ein Problem auf, wenn versucht wird, den MouseExit-Listener dazu zu bringen, eine "close" -Methode auszulösen, NUR wenn die Maus die gesamte Menüstruktur verlassen hat (dh die Dropdown-Menüs untergeordnete Menüs).

Unten finden Sie eine voll funktionsfähige Antwort von meinem Live-App wurde:

So wie ich das Menü aus der Nähe auf der Maus gelöst war eine boolesche Variable „isMouseOut“ in der Spitze des Konstruktor zu laufen, um zu verfolgen , und weisen Sie dann den MouseListener einer OO-freundlicheren Weise zu, um die verschiedenen MouseIn-MouseOut-Ereignisse zu verfolgen, wenn ein Benutzer mit dem Menü interagiert. Dies ruft eine separate menuClear-Methode auf, die auf den Zustand des Boolean "isMouseOut" einwirkt. Die Klasse implementiert MouseListener. So ist es gemacht.

Erstellen Sie eine ArrayList, die zuerst alle Menüelemente zu diesem Array hinzufügt.Wie so:

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); 

iteriert dann über die Arraylist in diesem Stadium ein Mouselistener Zugabe mit dem für() Schleife:

for (Component c : aMenuItms) { 
     if (c instanceof JMenuItem) { 
      c.addMouseListener(ml); 
     } 
    } 

Nun setzen JMenu Eltern für das MenuBar:

// 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); 

Fügen Sie dann die Dropdown-Menüelemente Kinder zu den JMenu-Eltern hinzu:

// 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); 

Fügen Sie die mouseListeners den JMenu Eltern als separater Schritt:

for (Component c : menuBar.getComponents()) { 
     if (c instanceof JMenu) { 
      c.addMouseListener(ml); 
     } 
    } 

Jetzt, wo das Kind menuItem Elemente alle ihre eigenen Zuhörer haben, die den Elementen JMenu Eltern getrennt sind und die MenuBar selbst - Es ist wichtig zu erkennen der Objekttyp innerhalb der MouseListener() - Instantiierung, damit das Menü beim MouseOver automatisch geöffnet wird (in diesem Beispiel die 3x JMenu - Eltern) ABER AUCH vermeidet Kindausnahmefehler und erlaubt eine saubere Identifikation von mouseOUT der Menüstruktur ohne zu überwachen, wo Mausposition ist. Der Mouselistener ist wie folgt:

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(); 
      } 
     } 
    }; 

Die oben simuliert nur die Maus in den (3x in diesem Beispiel) ‚Eltern‘ JMenu klicken, da sie die Auslöser für die untergeordnete Menü-Dropdown-Listen sind. Die timerMenuClear() -Methode ruft den MenuSelectionManager zum Zeitpunkt der realen mouseOut Live was auch immer SelectedPath Punkt zu leer war:

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(); 
} 

Es hat mir eine wenig Prüfung, Überwachung, welche Werte ich in der JVM während seiner Entwicklung zugreifen konnte - aber es funktioniert ein Vergnügen! sogar mit verschachtelten Menüs :) Ich hoffe, dass viele dieses vollständige Beispiel sehr nützlich finden.