我正在开发一个简单的Java swing项目。这是主类的代码(名称已更改):
public class MainProg
{
private static MainProg program;
//mainWin is a JFrame
private MainWindow mainWin;
//Event handler class which extends MouseAdapter
private TrayManager trayMgr;
public static void main(String[] args)
{
program = new MainProg();
}
public MainProg()
{
mainWin = new MainWindow();
trayMgr = new TrayManager();
mainWin.startBtn.addMouseListener(trayMgr);
mainWin.setVisible(true);
}
}
很明显,当程序启动时,在main()
中它会创建一个MainProg
类的新实例,然后调用构造函数。在构造函数中,它创建了JFrame mainWin
的新实例。然后它将事件处理程序附加到mainWin
上的按钮。
在事件处理程序类trayMgr
中,唯一的方法是mouseClicked()
,它什么都不做
除了System.out.println('Clicked');
问题是,当我在Netbeans中运行此程序时,会立即显示JFrame,但我似乎必须在控制台中打印消息之前单击按钮2-3次。
这只是Netbeans的特定内容,还是我必须更改某些内容才能在窗口可见之前设置事件处理程序?
答案 0 :(得分:5)
您的线程问题不太可能导致您当前的问题,但是存在问题的理论潜力,并且我已经看到一些与一些更敏感的外观和感觉相关的实际问题。很简单,您应该将启动GUI的代码排队到Swing事件线程中。你这样做:
public void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(
public void run() {
program = new MainProg();
}
));
}
其他人建议使用invokeAndWait(...)
而不是invokeLater(...)
,但这可能会有风险,尤其是如果您无意中从Swing事件线程本身进行此调用。根据您的情况,您最好使用invokeLater(...)
。
但同样,我认为您所显示的代码的主要问题是不恰当地使用了应该使用ActionListener的MouseListener。学习编写任何GUI库都非常棘手,因此,你不能假设任何东西。查看教程并向专家学习。此外,如果您正在考虑长期编写Swing,请考虑放弃NetBean的代码生成实用程序,并首先学习手动编写Swing代码。你不会后悔这样做。
答案 1 :(得分:3)
因为您问过,我在不同主题上发布了here is a Java SSCCE的代码。 invokeLater
是一种在EDT上运行计算的方法。 (还有invokeAndWait
,这在这里可以正常工作,但在某些其他条件下可能会导致死锁。)
事实上这个例子可能有点过于保守了。一些参考文献说你可以从主线程运行Swing,调用show()
或setVisible()
。但是,当我尝试时,我有一个在Java 7下行为不端的程序。