我的Java Swing应用程序启动时需要运行一些初始化代码,而不会触发任何事件。

我的初始化代码在myInits()函数中。 myInits()做各种事情:从文件读取配置,设置背景和一些标签,生成网络线程,初始化变量。

通过谷歌搜索和我自己的知识,我找到了实现此目标的不同方法(如果以下陈述的任何假设是错误的,请纠正我):


触发myInits()事件时,运行Window_Opened


这样可以确保GUI绘制成功,并且myInits()可以访问任何组件并进行更改。不幸的是,我无法使用此方法,因为我的应用程序开始隐藏并且Window_Opened未被触发。




myInits()放在JFrame构造函数中:

public class MyFrame extends javax.swing.JFrame {

    private MyFrame(){

        initComponents();  // <= Auto generated by NetBeans GUI Builder

        myInits();

    }
}



我想这种方法没有错,因为initComponents()本身可以进行各种GUI操作。我使用了这种方法,效果很好。

但是今天我将MyFrame更改为Singleton,并得到了java.lang.ExceptionInInitializerError。因为myInits()调用MyFrame.getInstance()并将其放入构造函数中,所以我在技术上是在另一个getInstance()内部调用getInstance()。我尝试制作getInstance() synchronized,但是没有用。




创建myInits() public并从main()调用它:

public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new ChatFrame().myInits();
        }
    });
}



我个人不喜欢这种方法,因为我不希望myInits()public。也因为我更喜欢4号。




构造函数中的invokeLater myInits()

private myFrame(){

    initComponents();

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run(){
            myInits();
        }
    });


}



这就是我自己想出的。因为实例化本身是在invokeLater()方法中完成的(请参见编号3),所以我认为我可以确定myInits()将在new myFrame();完成后运行,并且我可以安全地调用MyFrame.getInstance()



把它们加起来:

1)所有这些方法正确吗?

2)是否将其中任何一种(或我可能未提及的其他可能方法)视为最佳实践?

3)Singleton JFrame的最佳做法是哪一种?

4)为什么当我synchronized我的getInstance()方法时我仍然得到java.lang.ExceptionInInitializerError

最佳答案

我认为,如果您的初始化逻辑不是特定于ui的,那么它应该是主要的。从myinit中提取一个单独的类,然后在main中调用它。

您也可以使用枚举使它成为单例,然后使用它,以便在首次使用/应用程序加载时对其进行初始化。

10-04 23:33