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.
Masz dobry powód, dla którego chcesz to zrobić? Wszystkie menu we wszystkich aplikacjach zachowują się w ten sposób. – Robin
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