使用Java7在OSX上启用Swing菜单

时间:2013-04-17 10:39:42

标签: java macos swing java-7 jmenu

我有一个swing应用程序,我需要从另一个线程启用JMenu。我在OSX上这样做,并通过apple.laf.useScreenMenuBar使用本机屏幕菜单。由于切换到java 7,最初禁用的菜单现在永远不会启用,我无法找出原因。我附上了一个说明问题的小程序。点击固定>更改菜单项应在短暂暂停后启用测试菜单(对话框应打开和关闭)。

使用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();
    }

}

1 个答案:

答案 0 :(得分:0)

我认为问题的根源是你的setVisible(false)在Swing线程之外。将其移至invokeLater()调用内部似乎更正确,并为您提供预期的行为。

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