Первоначальный и принятый ответ Roman C не будет автоматически закрывать меню с дочерними MenuItems как часть JMenuBar.
Запуск ((JMenu) e.getSource ()). DoClick (); on the mouseEntered имитирует щелчок по одному из родительских элементов JMenu, но его нельзя просто добавить в метод mouseExited, поскольку MouseListener необходимо прикрепить к дочерним элементам MenuItems, а также к родительским элементам JMenu. (Этого не происходит при обычном назначении MenuBar - только присоединение к родительским объектам JMenu).
Кроме того, проблема возникает из-за попытки заставить прослушиватель MouseExit запускать метод «закрытия» ТОЛЬКО, когда мышь покидает всю структуру меню (то есть раскрывающееся меню дочернего меню).
Ниже приведен полностью рабочий ответ, взятый из моего действующего приложения:
Способ, которым я решил закрывать меню при выходе мыши, заключался в том, чтобы запустить логическую переменную isMouseOut в верхней части конструктора для отслеживания, а затем выделить 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 на этом этапе, добавив MouseListener, используя цикл for ():
for (Component c : aMenuItms) {
if (c instanceof JMenuItem) {
c.addMouseListener(ml);
}
}
Теперь установите родителей JMenu для 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);
Затем добавьте дочерние элементы раскрывающегося меню к родительским элементам 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 выглядит следующим образом:
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 (3 раза в этом примере), поскольку они являются триггерами для раскрывающихся списков дочернего меню. Метод timerMenuClear () вызывает MenuSelectionManager, чтобы очистить любую точку selectedpath, которая была активна во время реального 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 во время ее разработки - но это работает! даже с вложенными меню :) Надеюсь, этот полный пример многим будет очень полезен.
person
Martin Sansone - MiOEE
schedule
02.01.2015