下面的代码是我用Eclipse开发的小型Java应用程序的启动画面的实现。启动画面在PC上运行良好,但在MAC上运行不正常。在MAC OSX上,首先出现的帧在2秒内出现灰色区域,然后在4秒的剩余时间内出现图像。图像通常应立即显示,持续时间为4秒。您是否知道为什么在图像出现在MAC上之前有延迟,而一切都在PC上运行良好? PS:我已经将应用程序部署为可执行的Jar,并且我在所有计算机上都使用Java 8。谢谢。
public static void main(String[] args)
{
SplashScreen splSplashScreen = new SplashScreen();
//Main window
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale();
}
public class SplashScreen extends JWindow
{
/**
* Numéro de série
*/
private static final long serialVersionUID = 1592663893301307318L;
private final static long TEMP_AFFICHAGE = 4000;
/**
* Constructeur par initialisation
* @param p_Frame Frame
* @param p_TempsAffichage Temps d'affichage en millisecondes
*/
public SplashScreen()
{
super(new Frame());
JLabel lblImage = new JLabel(new ImageIcon(this.getClass().getResource("/res/ui/splashScreen.jpg")));
Container container = this.getContentPane();
container.add(lblImage, BorderLayout.CENTER);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension labelSize = lblImage.getPreferredSize();
this.setLocation(screenSize.width/2 - (labelSize.width/2), screenSize.height/2 - (labelSize.height/2));
this.setVisible(true);
try
{
Thread.sleep(TEMP_AFFICHAGE);
}
catch (InterruptedException ex)
{
ApplicationLogger.getInstance().severe(ex.getLocalizedMessage());
}
finally
{
this.setVisible(false);
}
}
}
答案 0 :(得分:2)
修改这与原始答案完全不同;我将在下面留下原来的答案。
看起来最初的JLabel渲染在OSX上是狗慢 - 删除所有睡眠仍然让我在Java呈现标签时暂停约2秒。所以我们改变了规则。
首先,我们创建一个采用缓冲图像的JPanel类:
class ImgPanel extends JPanel {
private BufferedImage img;
public ImgPanel(BufferedImage img) {
this.img = img;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
}
然后我们像这样更改启动画面构造函数:
public SplashScreen()
{
BufferedImage img = null;
try {
img = ImageIO.read(this.getClass().getResource("/res/ui/splashScreen.jpg"));
} catch (Exception ex) {
}
ImgPanel panel = new ImgPanel(img);
Container container = this.getContentPane();
container.add(panel);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(screenSize.width/2 - (img.getWidth()/2), screenSize.height/2 - (img.getHeight()/2));
this.setVisible(true);
}
一旦面板出现而没有暂停,这将呈现图像。
注意 - 我删除了整个睡眠代码以减少混淆 - 在单独的SwingWorker中可以更好地捕获逻辑,以执行启动画面的隐藏和主屏幕的显示:
class worker extends SwingWorker<String, Object> {
private final static long TEMP_AFFICHAGE = 4000;
private SplashScreen splash;
private FenetrePrincipale principale;
public worker(SplashScreen splash, FenetrePrincipale principale) {
this.splash = splash;
this.principale = principale;
this.splash.setVisible(true);
}
@Override
public String doInBackground() {
try
{
Thread.sleep(TEMP_AFFICHAGE);
}
catch (InterruptedException ex)
{
ApplicationLogger.getInstance().severe(ex.getLocalizedMessage());
}
return "";
}
@Override
protected void done() {
splash.setVisible(false);
principale.setVisible(true);
}
};
然后主代码如下:
public static void main(String[] args)
{
SplashScreen splSplashScreen = new SplashScreen();
//Main window
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale();
worker w = new worker(splSplashScreen, fenetrePrincipale);
w.execute();
}
原始答案 - 将休眠线程放入SwingWorker仍然是一个好主意,因为它可以让您在初始化之前执行实际工作。
好的,一个简单的例子,使用你的启动代码将休眠放入gui线程 - 这段代码在this.setVisible(true)
之后,并替换try {} catch {} finally {}子句:
this.setVisible(true);
worker do_work = new worker(this);
do_work.execute();
}
class worker extends SwingWorker<String, Object> {
private SplashScreen parent;
public worker(SplashScreen parent) {
this.parent = parent;
}
@Override
public String doInBackground() {
try
{
Thread.sleep(TEMP_AFFICHAGE);
}
catch (InterruptedException ex)
{
ApplicationLogger.getInstance().severe(ex.getLocalizedMessage());
}
return "";
}
@Override
protected void done() {
parent.setVisible(false);
}
};
我只是创建一个SwingWorker,它以doWorkInBackground
进行休眠,一旦结束,它就会关闭父帧,即启动画面。