我有一个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();
}
}
答案 0 :(得分:0)
我认为问题的根源是你的setVisible(false)
在Swing线程之外。将其移至invokeLater()
调用内部似乎更正确,并为您提供预期的行为。
EventQueue.invokeLater(new Runnable() {
public void run() {
window.makeVisible();
setVisible(false);
}
});