Активировать JMenuBar при наведении



JMenuBar не начинает показыватьJMenuItem S как выбранный или отображать всплывающие окнаJMenu , пока на него не нажмут. После того, как вы нажмете где-нибудь в JMenuBar, все эти элементы реагируют на наведение курсора мыши.



Я хотел бы обойти обязательный начальный щелчок и активировать его автоматически при наведении мыши. Есть ли способ сделать это?

555   2  

2 ответов:

Способ состоит в том, чтобы добавить MouseListener на JMenu и слушать события mouseEntered. В обработчиках событий вам просто нужно нажать на него, используя doClick. Например,

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

После того, как программно нажата на мышь, она автоматически открывает всплывающее меню. Чтобы активировать весь JMenuBar, Вы должны добавить слушателя на каждом JMenu. Для этого лучше создать объект прослушивателя отдельно.

У меня есть два пункта меню на панели, так что я сделал:

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

Если у вас так многие пункты меню на панели, вы можете просто повторить его:

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

Первоначальный и принятый ответ романа с не будет автоматически закрывать меню с дочерними меню как часть JMenuBar.

Запуск a ((JMenu)e. getSource ()).doClick (); на mouseEntered имитирует щелчок в один из родителей JMenu, но не может быть просто добавлен в метод mouseExited, так как MouseListener должен быть присоединен к дочерним MenuItems, а также к родителям JMenu. (Чего он не делает в обычном назначении к MenuBar-только прикрепление к родительскому JMenu объекты).

Кроме того, проблема возникает из-за попытки заставить прослушиватель MouseExit запускать метод "close" только тогда, когда мышь покинула всю структуру меню (т. е. дочерние раскрывающиеся меню).

Ниже приведен полностью рабочий ответ, взятый из моего живого приложения:

Способ, которым я решил меню close on mouse out, состоял в том, чтобы запустить булеву переменную "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 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 'родители' (3x в этом примере), поскольку они являются триггерами для выпадающих меню дочернего. Метод timerMenuClear() вызывает MenuSelectionManager, чтобы очистить любую выбранную точку пути, которая была в реальном времени во время реального времени. 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 во время его разработки - но это работает здорово! даже с вложенными меню:) я надеюсь, что многие найдут этот полный пример очень полезным.

Comments

    Ничего не найдено.