【发布时间】:2012-08-13 11:07:52
【问题描述】:
这是我的初始屏幕代码,
public class SplashScreen extends JWindow {
private static final long serialVersionUID = 1L;
private BorderLayout borderLayout = new BorderLayout();
private JLabel imageLabel = new JLabel();
private JProgressBar progressBar = new JProgressBar(0, 100);
public SplashScreen(ImageIcon imageIcon) {
imageLabel.setIcon(imageIcon);
setLayout(borderLayout);
add(imageLabel, BorderLayout.CENTER);
add(progressBar, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
}
public void showScreen() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setVisible(true);
}
});
}
public void close() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setVisible(false);
dispose();
}
});
}
public void setProgress(final String message, final int progress) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(progress);
if (message == null) {
progressBar.setStringPainted(false);
} else {
progressBar.setStringPainted(true);
}
progressBar.setString("Loading " + message + "...");
}
});
}
}
从我这样调用的主要方法中,
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
SplashScreen splashScreen = new SplashScreen(new ImageIcon("images/splash.jpg"));
splashScreen.showScreen();
AppFrame frame = new AppFrame(splashScreen);
} catch (Exception e) {
appLogger.error(e.getMessage(), e);
}
}
});
}
在我调用的 AppFrame 的构造函数中, splashScreen.setProgress(msg, val) 更新进度条的方法。但飞溅没有显示。它仅在最后显示帧仅显示几分之一秒,即使加载需要很长时间。但是如果我把这三行
SplashScreen splashScreen = new SplashScreen(new ImageIcon("images/splash.jpg"));
splashScreen.showScreen();
AppFrame frame = new AppFrame(splashScreen);
在 invokeLater() 之外,会显示初始屏幕并且进度条会很好地更新。我相信 GUI 更新应该在 invokeLater 中。可能是什么问题?
顺便说一句,AppFrame 会加载我的应用程序的各种面板。
编辑: 我的 AppFrame 的模拟如下所示。
public class AppFrame extends JFrame {
public AppFrame(SplashScreen splashScreen) {
JPanel test = new JPanel();
test.setLayout(new GridLayout(0, 10));
splashScreen.setProgress("jlabel", 10);
for(int i = 0; i < 10000; i++) {
test.add(new JButton("Hi..." + i));
splashScreen.setProgress("jbutton", (int)(i * 0.1));
}
add(new JScrollPane(test));
setPreferredSize(new Dimension(800, 600));
pack();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
splashScreen.setProgress("complete", 100);
setVisible(true);
}
}
【问题讨论】:
-
" 我认为 GUI 更新应该在 invokeLater 中。" 或
invokeAndWait。但是做一些记录,我希望你会发现完成splashScreen.showScreen();和AppFrame frame = new AppFrame(splashScreen);之间的时间比你预期的要少得多。另请注意,最好的飞溅是严格的 AWT(没有 Swing)。 -
这意味着我应该使用 Window 或 Frame 而不是 JWindow?谢谢。
-
是的,使用
Window或Frame。还要查看MediaTracker/Canvas和EventQueue- 必须没有使用 Swing 导入或类,或者首先加载整个 Swing 包。 -
还可以考虑使用java-web-start 启动画面。
-
嗯……真的是ui创建需要这么长时间吗?如果没有,请提取 real 时间消耗 (!ui = !EDT) 并在 SwingWorker 的 doInBackground 中准备它们,将中间进度发布到启动画面并在完成时关闭启动画面/显示应用程序跨度>
标签: java swing splash-screen jprogressbar invokelater