簡體   English   中英

Java啟動畫面無法在Mac OSX上運行,但可以在PC上運行

[英]Java splash screen not working on Mac OSX but working on a PC

下面的代碼是我用Eclipse開發的一個小型Java應用程序的啟動屏幕的實現。 初始屏幕在PC上可完美運行,但在MAC上則無法完美運行。 在MAC OSX上,該框首先在2秒鍾內出現一個灰色區域,然后在剩下的4秒鍾內出現該圖像。 該圖像通常應立即顯示並持續4秒鍾。 您是否知道為什么在PC上一切正常時,圖像出現在MAC上會有一定的延遲? 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);
        }
    }
}

編輯這與原始答案完全不同。 我將在下面保留原始答案。

看起來最初的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一樣進行睡眠,一旦結束,它將關閉父框架,即初始屏幕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM