【问题标题】:GUI has to wait until splashscreen finishes executingGUI 必须等到启动画面完成执行
【发布时间】:2015-03-26 22:39:53
【问题描述】:

我有一个 SplashScreen 类,它显示图像和进度条,直到某些数据库被初始化。我希望在启动画面结束后打开一个新窗口。我有以下代码:

主类

public class Gui{

private static final String IMG_PATH = "../opt/images/splashscreendef.jpg";

public static void main(String[] args) throws ClassNotFoundException,
        InstantiationException, IllegalAccessException,
        UnsupportedLookAndFeelException {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            Gui ui = new Gui();
        }
    });
}

private inTouchGui() {
    InitSplashScreen splash = null;
    splash = new InitSplashScreen();
    try {
        splash.initUI();
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    BufferedImage img = null;
    try {
        img = ImageIO.read(new File(IMG_PATH));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ImageIcon icon = new ImageIcon(img);
    JLabel label = new JLabel(icon);
    JOptionPane.showMessageDialog(null, label);
}

}

闪屏类

public class InitSplashScreen {
private JDialog dialog;
private JProgressBar progress;

public void initUI() throws MalformedURLException {
    showSplashScreen();
    SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>(){

        @Override
        protected Void doInBackground() throws Exception {
            Thread thread = new Thread(new InitProcess());
            thread.start();
            int i = 0;
            while (thread.isAlive()){
                i++;
                Thread.sleep(200);// Loading of databases
                publish(i);// Notify progress
            }
            if (i < 10){
                for (i = 0; i < 100; i++){
                    Thread.sleep(50);// We simulate loading even if database is fully loaded
                    publish(i);// Notify progress
                }
            }
            return null;
        }

        @Override
        protected void process(List<Integer> chunks) {
            progress.setValue(chunks.get(chunks.size() - 1));
        }

        @Override
        protected void done() {
            hideSplashScreen();
        }

    };
    worker.execute();
}



protected void hideSplashScreen() {
    dialog.setVisible(false);
    dialog.dispose();
}

protected void showSplashScreen() throws MalformedURLException {
    dialog = new JDialog((Frame) null);
    dialog.setModal(false);
    dialog.setUndecorated(true);
    JLabel background = new JLabel(new ImageIcon("splashscreendef.jpg"));
    background.setLayout(new BorderLayout());
    dialog.add(background);
    progress = new JProgressBar();
    background.add(progress, BorderLayout.SOUTH);
    dialog.pack();
    dialog.setLocationRelativeTo(null);
    dialog.setVisible(true);
}

}

当我运行代码时,我同时获得了启动屏幕和图像窗口,我尝试使用worker.get(),但屏幕上什么也没有出现。你能给我一些建议吗?我对 Java Swing 还很陌生。

顺便说一句,例如,是否有可能实现一个像这样的登录窗口(可能意味着不是疯狂的代码负载和使其工作的时间)?

http://designsparkle.com/wp-content/uploads/2014/06/a-simple-html-css-login-for.jpg

感谢您的建议。

【问题讨论】:

    标签: java swing concurrency swingworker


    【解决方案1】:

    改变你的思维方式

    初始化并显示启动画面,完成后,初始化并显示Gui

    这需要有一些方法来告诉谁初始化了初始屏幕它已经完成,为此,您可以使用PropertyChangeListener...

    public class InitSplashScreen {
        //...
        public void initUI(PropertyChangeListener listener) throws MalformedURLException {
            showSplashScreen();
            SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
                //...
            };
            worker.addPropertyChangeListener(listener);
            worker.execute();
        }
    

    然后你监听state更改属性并检查工作状态...

    public static void main(String[] args) throws ClassNotFoundException,
                    InstantiationException, IllegalAccessException,
                    UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                InitSplashScreen splashScreen = new InitSplashScreen();
                try {
                    splashScreen.initUI(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String name = evt.getPropertyName();
                            if ("state".equalsIgnoreCase(name)) {
                                SwingWorker worker = (SwingWorker) evt.getSource();
                                if (worker.getState().equals(SwingWorker.StateValue.DONE)) {
                                    Gui ui = new Gui();
                                }
                            }
                        }
                    });
                } catch (MalformedURLException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }
    

    但请记住,您需要从 Gui 代码中删除启动画面。

    您还可以使用它从SwingWorker“获取”Gui 可能需要的任何信息,并将其作为参数传递给构造函数或根据您的需要通过设置器传递

    另外,对我来说,这...

    Thread thread = new Thread(new InitProcess());
    thread.start();
    

    SwingWoker 中做这件事似乎很奇怪。如果您不知道需要多少工作,您可以简单地将JProgressBar 留在indeterminate 模式

    【讨论】:

    • 非常感谢您的建议和回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2011-07-16
    • 1970-01-01
    相关资源
    最近更新 更多