1

我正在做一个简单的 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 特有的,还是我必须更改某些内容才能在窗口可见之前设置事件处理程序?

4

2 回答 2

5

您的线程问题不太可能导致您当前的问题,但理论上存在问题的可能性,而且我已经看到一些与一些更敏感的外观和感觉相关的实际问题。很简单,您应该将启动 GUI 的代码排入 Swing 事件线程。你这样做:

public void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable(
    public void run() {
      program = new MainProg();
    }
  ));
}

其他人建议使用invokeAndWait(...)而不是,invokeLater(...)但这可能会有风险,特别是如果您无意中从 Swing 事件线程本身进行了此调用。对于您的情况,您最好使用invokeLater(...).

但同样,我认为您显示的代码的主要问题是不恰当地使用 MouseListener,而应该使用 ActionListener。学习编写任何 GUI 库的代码可能非常棘手,因此,您不能假设任何事情。查看教程并向专家学习。此外,如果您正在考虑长期编写 Swing 代码,请考虑放弃 NetBean 的代码生成实用程序,并首先学习手动编写 Swing 代码。你不会后悔这样做的。

于 2012-09-05T02:07:34.650 回答
3

既然你问了,我在这里发布的代码是关于不同主题的 Java SSCCE 。invokeLater是在 EDT 上运行计算的一种方式。(还有invokeAndWait,在这里可以正常工作,但在某些其他情况下可能会导致死锁。)

事实上,这个例子可能有点过于保守了。一些参考资料说您可以从调用show()或的主线程运行 Swing setVisible()。但是,当我尝试时,我有一个在 Java 7 下行为不端的程序。

于 2012-09-05T01:37:22.120 回答