添加JFrame事件处理程序之前的滞后?

Cli*_*ote 1 java concurrency swing netbeans event-dispatch-thread

我正在开发一个简单的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

很明显,当程序启动时,main()它会创建一个新的MainProg类实例,然后调用构造函数.在构造函数中,它创建JFrame的新实例mainWin.然后它将事件处理程序附加到按钮上mainWin.

在事件处理程序类中trayMgr,唯一的方法是mouseClicked()除了a之外什么都不做System.out.println('Clicked');

问题是,当我在Netbeans中运行此程序时,JFrame立即显示,但我似乎必须在控制台中打印消息之前单击按钮2-3次.

这只是Netbeans的特定内容,还是我必须更改某些内容才能在窗口可见之前设置事件处理程序?

Hov*_*els 5

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

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

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

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

  • 我必须先建议您先学习如何手动编写Swing代码.我有相当多的这样做,我刚刚开始学习如何使用NetBeans GUI Builder.我最近在Stackoverflow上提出的许多Java问题都是关于使用GUI Builder的.总的来说,我觉得它不合适,很可能会完全不再使用它来进行未来的项目. (2认同)