2012-08-25 10 views
7

Pasek JMenuBar nie zaczyna się wyświetlać JMenuItem s jako wybrane lub wyświetlanie wyskakujących okienek JMenu, dopóki nie zostanie po raz pierwszy kliknięty. Po kliknięciu gdzieś w numerze JMenuBar wszystkie te elementy odpowiadają na ruchy myszy.Aktywuj pasek JMenuBar po najechaniu myszą

Chciałbym pominąć wymagane początkowe kliknięcie i aktywować je automatycznie po najechaniu kursorem myszy. Czy jest jakiś sposób na zrobienie tego?

+3

Masz dobry powód, dla którego chcesz to zrobić? Wszystkie menu we wszystkich aplikacjach zachowują się w ten sposób. – Robin

+0

Cóż, moje menu ma niestandardowy wygląd, a to zachowanie pasuje do niego bardziej naturalnie. Uważam również, że to zachowanie jest o wiele bardziej interaktywne dla użytkownika. – springcorn

Odpowiedz

9

Sposób na dodanie MouseListener na JMenu i słuchanie wydarzeń mouseEntered. W procedurach obsługi zdarzeń wystarczy kliknąć na nie, używając doClick. Na przykład:

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

Po kliknięciu myszką po kliknięciu myszą menu podręczne zostanie automatycznie otwarte. Aby aktywować cały JMenuBar, musisz dodać detektor na każdym JMenu. W tym celu lepiej jest osobno utworzyć obiekt nasłuchu.

mam dwie pozycje menu na pasku, tak zrobiłem:

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

Jeśli masz tak wiele elementów menu na pasku, można po prostu iteracyjne go:

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

Rozumiem detektor mouseEntered, ale jak aktywować cały JMenuBar z myszy? – springcorn

+0

właśnie edytowane powyżej –

+0

Dzięki. To postawiło mnie na dobrej drodze, ale myślę, że miałem nadzieję, że był prostszy sposób na zrobienie tego, jak jMenuBar.activate(), zamiast pojedynczego wymuszania kliknięcia. Dla JMenuItem nie można wywołać metody doClick(), ale uważam, że najlepszym sposobem wygenerowania tego zachowania jest setArmed (true) – springcorn

1

Roman C na początkowa i zaakceptowana odpowiedź nie będzie AUTO Zamknij menu z dzieckiem MenuItems jako część JMenuBar.

Uruchamianie ((JMenu) e.getSource()). DoClick(); na mouseEntered symuluje kliknięcie w jednym z rodziców JMenu, ale nie można go dodać do metody MouseExited, ponieważ MouseListener musi być dołączony do potomnych MenuItems, jak również rodziców JMenu. (Którego nie robi w normalnym przypisaniu do menuBar - tylko dołączanie do rodzica obiektów JMenu).

Dodatkowo, pojawia się problem z powodu próby uruchomienia detektora myszy MouseExit TYLKO metodą "zamknięcia", gdy mysz opuści całą strukturę menu (np. Menu rozwijane menu Dziecko).

Poniżej znajduje się odpowiedź w pełni pracy pochodzi z mojego żywo app:

Sposób, w jaki rozwiązał zamknąć menu na myszy out było uruchomić logiczną zmienną „isMouseOut” w górnej części konstruktora śledzić , a następnie przydzielić MouseListener w bardziej przyjazny dla OO sposób, aby śledzić wiele zdarzeń MouseIn-MouseOut, gdy użytkownik wchodzi w interakcję z menu. Który wywołuje osobną metodę menuClear działającą na stan boolean "isMouseOut". Klasa implementuje MouseListener. Tak to się robi.

Utwórz listę ArrayList, dodając najpierw wszystkie pozycje menu do tej tablicy.Tak:

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

następnie iteracyjne nad ArrayList na tym etapie dodając MouseListener pomocą dla() pętlę:

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

teraz ustawić rodziców JMenu dla 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); 

Następnie dodaj menu rozwijane Elementy dzieci do rodziców 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); 

Dodać mouseListeners rodzicom JMenu jako oddzielny etap:

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

teraz, że dziecko MENUITEM elementy mają swoje słuchaczy, które są oddzielone do elementów jednostki dominującej JMenu i samego MenuBar - Ważne jest, aby zidentyfikować typ obiektu w instancji MouseListener(), aby uzyskać automatyczne otwieranie menu po najechaniu myszką (w tym przykładzie rodzice 3x JMenu), ALE RÓWNIEŻ unika błędów wyjątków dla dzieci i pozwala na czystą identyfikację mouseOUT struktury menu bez prób monitorowania, gdzie pozycja myszy to. MouseListener jest następujący:

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

Powyższy symuluje tylko mysz Kliknij w JMenu „rodziców” (3x w tym przykładzie), ponieważ są one wyzwalaczy dla menu rozwijanego menu dziecka. Metoda timerMenuClear() wzywa MenuSelectionManager opróżnić cokolwiek selectedpath punkt był na żywo w czasie rzeczywistym 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(); 
} 

Zajęło mi trochę badań, monitorowania, jakie wartości mogę przejść w JVM podczas jego rozwoju - ale działa przyjemnie! nawet z zagnieżdżonymi menu :) Mam nadzieję, że wiele osób uzna ten pełny przykład za bardzo przydatny.

Powiązane problemy