2013-08-09 3 views
2

Этот вопрос является продолжением this question.JMenuItem ускоритель не работает, когда строка меню скрыта

У меня есть JMenuBar, поведение которого похоже на панели меню в Firefox и iTunes. То есть строка меню сначала скрыта, но когда вы нажимаете Alt, появляется строка меню.

Ответ на другой вопрос решается задача достижения этой функциональности, но это привело к другому вопроса: В JMenuItem Ускорителях не работает, когда JMenuBar не виден. Другими словами, вы должны нажать Alt до CTRL+F (установленный ускоритель).

Это не должно быть, однако, так как метод setAccelerator() гласит следующее:

общественной ничтожной setAccelerator (KeyStroke KeyStroke)

Устанавливает комбинацию клавиш, которая вызывающую действие пункта меню слушателей без навигации по иерархии меню. Ответственность за установку правильного действия лежит на пользовательском интерфейсе. Обратите внимание, что когда клавиатурный ускоритель вводится, он будет работать независимо от того, отображается ли в данный момент меню.

Итак, мне интересно, если это еще одна ошибка Java?

SSCCE (чтобы получить меню появится, вы нажимаете Alt и установлен ускоритель CTRL+F для «Найти», который воспитывает фиктивная JOptionPane для входа):

import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.KeyStroke; 
import javax.swing.MenuElement; 
import javax.swing.MenuSelectionManager; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.WindowConstants; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class MenuBarTest extends JFrame { 

    public MenuBarTest() { 
     JMenu jMenu1 = new JMenu(); 
     JMenu jMenu2 = new JMenu(); 
     final JMenuBar jMenuBar1 = new JMenuBar(); 
     JMenuItem jMenuItem1 = new JMenuItem(); 
     JMenuItem jMenuItem2 = new JMenuItem(); 

     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     jMenu1.setText("File"); 
     jMenuItem1.setText("jMenuItem1"); 
     jMenu1.add(jMenuItem1); 
     jMenuBar1.add(jMenu1); 
     jMenu2.setText("Edit"); 
     jMenuItem2.setText("Find"); 
     jMenu2.add(jMenuItem2); 
     jMenuBar1.add(jMenu2); 
     setJMenuBar(jMenuBar1); 

     jMenuBar1.setVisible(false); 
     ChangeListener listener = new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath(); 
       jMenuBar1.setVisible(elements.length > 0 && elements[0] == jMenuBar1); 
      } 
     }; 
     MenuSelectionManager.defaultManager().addChangeListener(listener); 

     jMenuItem2.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK)); 
     jMenuItem2.setText("Find"); 
     jMenuItem2.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       String what = JOptionPane.showInputDialog(MenuBarTest.this, "Search for what?"); 
       System.out.println(what); 
      } 
     }); 

     pack(); 
     setSize(500,500); 
     setLocationRelativeTo(null); 
     setVisible(true); 
    } 

    public static void main(String args[]) { 
     try { 
      UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
      ex.printStackTrace(); 
     } 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new MenuBarTest(); 
      } 
     }); 
    } 
} 
+0

мое дело в том, что это проблема с документацией: здесь отображается «отображается», что означает нормальное состояние, что меню/элемент под панелью меню скрыто (потому что мы видим только строку меню). Тем не менее, это _showing_ (потому что это видно, и все его предки показывают), таким образом позволяя привязки работать. – kleopatra

ответ

3

Прочитайте акцент тщательно

Обратите внимание, что когда клавиатурный ускоритель вводится, он будет работать независимо от того, отображается ли в данный момент меню.

Это говорит о меню не его родитель. Это означает, что меню может не отображаться в настоящее время. Тем не менее, реальным (возможно, не слишком хорошо документированным) желательным свойством является то, что он должен быть , показывая. Обновил свой ответ на ваш предыдущий вопрос.

+0

Ничего себе. Как последний вопрос, я бы никогда об этом не подумал сам. В этом сообществе полно талантливых разработчиков! – ryvantage

+0

О, как я люблю Java ... Итак, я расширил JMenuBar и (хорошо, не бросайте помидоры на меня) попытался импортировать новый класс в Netbeans (да, GUI-строитель), и я столкнулся с этой забавой Немного подробностей: не все методы JMenuBar завершены. Кто-то пожаловался на это (получите это) в 1999 году: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4087846, и он STILL не был исправлен. Статья в блоге, точно названная «wtf», была создана в честь этой ошибки .. в, о, 2006. http://tsareto.blogspot.com/2006/05/wtf.html. Поэтому не называйте 'JMenuBar.getHelpMenu()', потому что Java еще не добрался до него. – ryvantage

+0

SSCCE: 'public static void main (String [] args) { JMenuBar bar = new JMenuBar(); bar.getHelpMenu(); } ' – ryvantage

Смежные вопросы