Не удается повторно включить строку меню OSX

У меня есть программа, которая использует несколько разных JMenuBar для разных окон (через JFrame.setJMenuBar()). Мы обнаружили, что в OSX в определенных ситуациях одна из этих полос меню может быть отключена, и, по-видимому, невозможно повторно включить ее после того, как это произошло. Вот мой простой пример:

public class Demo {

   public static void main(String[] args) {
      System.setProperty("apple.laf.useScreenMenuBar", "true");
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      }
      catch (Exception e) {
         System.out.println("Error setting LAF: " + e);
      }
      new MyFrame("Alpha frame");
      new MyFrame("Beta frame");
   }

   public static class MyFrame extends JFrame {
      public MyFrame(String title) {
         super(title);
         final JMenuBar menuBar = new JMenuBar();
         JButton button = new JButton("Toggle menu") {
            @Override 
            public Dimension getPreferredSize() {
               return new Dimension(300, 300);
            }
         };
         add(button);
         button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               menuBar.setEnabled(!menuBar.isEnabled());
            }
         }); 

         JMenu fileMenu = new JMenu("File");
         fileMenu.add(new JMenuItem("Dummy action"));
         menuBar.add(fileMenu);
         setJMenuBar(menuBar);
         pack();
         setVisible(true);
      } 
   }    
}

Если вы отключите одну из панелей меню кадра с помощью ее кнопки, затем переключите фокус на другой кадр, переключитесь назад и снова щелкните кнопку, панель меню не станет повторно активна визуально - пункты меню останутся серыми и неработоспособными, но isEnabled() вернет истину.

Это проблема, потому что некоторые модальные диалоговые окна автоматически отключают текущую строку меню. Я видел, как это происходило с JFileChooser, и я также видел, как это происходило с FileDialog. Также могут быть проблемы с исключениями в потоке отправки событий; Я не проводил подробного анализа. В идеале я бы просто удостоверился, что всякий раз, когда данное окно получает фокус, его строка меню автоматически повторно включается, но метод setEnabled() JMenuBar на самом деле ничего не делает, если вы переключили фокус на другое окно, как демонстрирует моя демонстрация. .

Как я могу это исправить?

(Java 6, к моему большому сожалению, мы обновим до Java 8, как только это будет физически возможно)

Спасибо за уделенное время.


person chris    schedule 18.11.2015    source источник
comment
Каким-то образом я пропустил эту аналогичную проблему в своих предыдущих поисках: stackoverflow.com/questions/32085966/. Переключение фокуса приложения приводит к правильному повторному включению меню. Однако это неправильное решение.   -  person chris    schedule 18.11.2015
comment
... и переключение фокуса приложения работает только иногда; большую часть времени меню все равно остается отключенным.   -  person chris    schedule 18.11.2015
comment
Ха. Выполнение setMenuBar(null) с последующим setJMenuBar(getJMenuBar()) исправляет все, кроме для меню "Справка", которое остается неисправным. Если я переименую наше меню «Справка» в «Справка 2», оно снова включится должным образом - очевидно, что справка - это особая строка какого-то типа в стиле OSX, и с ней неправильно обрабатываются. К сожалению, я не могу понять, как заставить меню справки делать то, что я хочу.   -  person chris    schedule 18.11.2015


Ответы (1)


Для меня я должен отключить JMenuItems, а не JMenuBar. Код для отключения строки меню:

for(int i = 0; i<menuBar.getMenuCount(); i++){
    JMenu menu = menuBar.getMenu(i);
    if(menu==null) continue;
    for(int j = 0; j<menu.getItemCount(); j++){
       JMenuItem item = menu.getItem(j);
       if(item==null) continue;
       item.setEnabled(false);
    }
}

Код для включения строки меню.

for(int i = 0; i<menuBar.getMenuCount(); i++){
    JMenu menu = menuBar.getMenu(i);
    if(menu==null) continue;
    for(int j = 0; j<menu.getItemCount(); j++){
       JMenuItem item = menu.getItem(j);
       if(item==null) continue;
       item.setEnabled(true);
    }
}
person matt    schedule 16.01.2017