![](/img/trans.png)
[英]Initialization of application and splash-screen with progress bar (Swing)
[英]Swing Splash screen with progress bar
這是我的啟動畫面代碼,
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);
}
}
嗯,看看我把這個使用SplashScreen
類放在一起的工作樣本(只使用一個簡單的Timer
和ActionListener
來增加ProgressBar
的值,直到100並顯示一個幀):
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SplashScreen extends JWindow {
private static JProgressBar progressBar = new JProgressBar();
private static SplashScreen splashScreen;
private static int count = 1, TIMER_PAUSE = 25,PROGBAR_MAX=100;
private static Timer progressBarTimer;
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
progressBar.setValue(count);
System.out.println(count);
if (PROGBAR_MAX == count) {
splashScreen.dispose();//dispose of splashscreen
progressBarTimer.stop();//stop the timer
createAndShowFrame();
}
count++;//increase counter
}
};
public SplashScreen() {
createSplash();
}
private void createSplash() {
Container container = getContentPane();
JPanel panel = new JPanel();
panel.setBorder(new javax.swing.border.EtchedBorder());
container.add(panel, BorderLayout.CENTER);
JLabel label = new JLabel("Hello World!");
label.setFont(new Font("Verdana", Font.BOLD, 14));
panel.add(label);
progressBar.setMaximum(PROGBAR_MAX);
container.add(progressBar, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setVisible(true);
startProgressBar();
}
private void startProgressBar() {
progressBarTimer = new Timer(TIMER_PAUSE, al);
progressBarTimer.start();
}
private void createAndShowFrame() {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
splashScreen = new SplashScreen();
}
});
}
}
從另一個invokeLater
調用invokedLater
。 只有在完成第一個執行時才會執行runnable
。
您應該像這樣修改Splashscreen代碼:
...
private void runInEdt(final Runnable runnable) {
if (SwingUtilities.isEventDispatchThread())
runnable.run();
else
SwingUtilities.invokeLater(runnable);
}
public void showScreen() {
runInEdt(new Runnable() {
public void run() {
setVisible(true);
}
});
}
public void close() {
runInEdt(new Runnable() {
public void run() {
setVisible(false);
dispose();
}
});
}
public void setProgress(final String message, final int progress) {
runInEdt(new Runnable() {
public void run() {
progressBar.setValue(progress);
if (message == null)
progressBar.setStringPainted(false);
else
progressBar.setStringPainted(true);
progressBar.setString("Loading " + message + "...");
}
});
}
Thread l_splash_thread = new Thread(
new SplashScreen ());
l_splash_thread.start();
try {
l_splash_thread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
我想這樣你可以保持你的潑水。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.