【问题标题】:Enabling Swing Menus on OSX with Java7使用 Java7 在 OSX 上启用 Swing 菜单
【发布时间】:2013-04-17 10:39:41
【问题描述】:

我有一个 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();
    }

}

【问题讨论】:

  • 不知道您的问题的答案(我在 Windows 上没有显示问题),但 +1 用于发布 SSCCE。
  • 它在 Ubuntu 上运行良好。无论如何,MainWindow 实例应该在 Event Dispatch Thread 上创建,因为它扩展了一个 swing 组件。
  • new MainWindow() 方法中的main 行也需要在EventQueue.invokeLater 内。不过,我不知道这是否能解决问题。
  • 我尝试将 MainWindow() 调用放入 invokeLater 调用中,但问题仍然存在。

标签: java macos swing java-7 jmenu


【解决方案1】:

我认为问题的根源在于您的 setVisible(false) 不在 Swing 线程中。将其移动到 invokeLater() 调用内部似乎更正确,并为您提供预期的行为。

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

【讨论】:

  • true 可能是使用 Thread.sleep(int) 而不是 Swing Timer
  • 如果 setVisible(false) 在 window.makeVisible() 之前,这仍然会失败。我得出的结论是,这是使用屏幕菜单栏时 OSX LAF 中的菜单切换代码中的错误。
猜你喜欢
  • 1970-01-01
  • 2012-04-11
  • 2012-05-17
  • 1970-01-01
  • 2012-01-31
  • 2014-10-05
  • 1970-01-01
  • 2016-06-25
  • 2012-08-12
相关资源
最近更新 更多