2013-04-17 2 views
4

У меня есть приложение поворота, в котором мне нужно включить JMenu из другого потока. Я делаю это на OSX, и я использую собственное экранное меню через apple.laf.useScreenMenuBar. С момента перехода на java 7 изначально отключенные меню теперь не включаются, и я не могу понять, почему. Я приложил небольшую программу, которая иллюстрирует проблему. При нажатии на пункт «Исправлено»> «Изменить» следует включить тестовое меню после короткой паузы (диалог должен открываться и закрываться).Включение меню Swing в OSX с помощью Java7

Использование java6 отлично работает. В java 7 меню не включено. Если я не использую экранное меню, оно работает в 6 или 7, и если я использую EventQueue.invokeAndWait, он работает в 6 или 7, но я не думаю, что мне нужно будет это делать.

Является ли это ошибкой, или я неправильно понимаю, как должны работать взаимодействия между качающимися нитями?

import java.awt.EventQueue; 
import java.awt.event.*; 
import javax.swing.*; 

public class MainWindow extends JFrame implements ActionListener { 

    private JMenu testMenu; 

    public MainWindow() { 

     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setTitle("Menu Enable Test"); 

     JMenuBar bar = new JMenuBar(); 

     JMenu fixedMenu = new JMenu("Fixed"); 
     JMenuItem change = new JMenuItem("Change"); 
     change.addActionListener(this); 
     fixedMenu.add(change); 
     bar.add(fixedMenu); 

     testMenu = new JMenu("Test"); 
     testMenu.setEnabled(false); 
     JMenuItem seeMe = new JMenuItem("Can you see me?"); 
     testMenu.add(seeMe); 

     bar.add(testMenu); 

     setJMenuBar(bar); 

     setSize(800,600); 
     setLocationRelativeTo(null); 
     setVisible(true); 
    } 

    public void makeVisible() { 
     testMenu.setEnabled(true); 
    } 

    public void actionPerformed(ActionEvent ae) { 
     new RemoteChanger(this); 
    } 

    private class RemoteChanger extends JDialog implements Runnable { 
     private MainWindow window; 

     public RemoteChanger (MainWindow window) { 
      super(window); 
      setSize(200,100); 
      setLocationRelativeTo(window); 
      this.window = window; 
      setVisible(true); 
      Thread t = new Thread(this); 
      t.start(); 
     } 

     public void run() { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) {} 

      EventQueue.invokeLater(new Runnable() { 
       public void run() { 
        window.makeVisible();     
       } 
      }); 

      setVisible(false); 

     } 
    } 

    public static void main (String [] args) { 
     System.setProperty("apple.laf.useScreenMenuBar", "true"); 
     new MainWindow(); 
    } 

} 
+0

Не знаю ответа на ваш вопрос (на Windows, который не отображает проблему), но +1 для публикации SSCCE. –

+0

Он отлично работает на Ubuntu. В любом случае экземпляр 'MainWindow' должен быть создан в Thread Dispatch Thread, поскольку он расширяет компонент swing. –

+0

Строка 'new MainWindow()' в 'main' также должна находиться внутри' EventQueue.invokeLater'. Однако я не знаю, решит ли это проблему. – VGR

ответ

0

Я считаю, что источником проблемы является ваш setVisible(false) находясь вне свинг нити. Перемещение его внутри вызова invokeLater() кажется более правильным и дает ожидаемое поведение.

EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     window.makeVisible();  
     setVisible(false); 
    } 
}); 
+0

true может быть использование Thread.sleep (int) вместо Swing Timer – mKorbel

+0

Это все еще не работает, если setVisible (false) идет перед window.makeVisible(). Я прихожу к выводу, что это ошибка в коде переключения меню в OSX LAF при использовании панели меню экрана. –