启动画面进度条不绘图

时间:2013-02-10 21:14:32

标签: java screen awt splash-screen event-dispatch-thread

我正试图在我的启动画面上创建自己的进度条。创建我的启动画面很简单:

  

java -splash:EaseMailMain.jpg Main.class   (来自Eclipse)

我的main方法的第一行称为:

new Thread(new Splash()).start();

这是启动类:

    public class Splash implements Runnable {
    public volatile static int percent = 0;
    @Override
    public void run() {
        System.out.println("Start");
        final SplashScreen splash = SplashScreen.getSplashScreen();
        if (splash == null) {
            System.out.println("SplashScreen.getSplashScreen() returned null");
            return;
        }
        Graphics2D g = splash.createGraphics();
        if (g == null) {
            System.out.println("g is null");
            return;
        }
        int height = splash.getSize().height;
        int width = splash.getSize().width;
        //g.drawOval(0, 0, 100, 100);
        g.setColor(Color.white);
        g.drawRect(0, height-50, width, 50);
        g.setColor(Color.BLACK);
        while(percent <= 100) {
            System.out.println((width*percent)/100);
            g.drawRect(0, height-50, (int)((width*percent)/100), 50);
            percent += 1;
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

我没有收到任何错误,但我确实在它下面放了一个小盒子:

The image with a rectangle below.

如果我将drawRects更改为(0,0,width,height),则没有任何区别。

我已尝试使用以下方式调用EDT:

SwingUtilities.invokeAndWait((new Splash()));

但没有任何反应。

有人能看到问题吗?或者知道如何解决它?

2 个答案:

答案 0 :(得分:4)

从其他线程更新GUI时,您应该使用SwingUtilities.invokeLaterSwingUtilities.invokeAndWait

请参阅章节Concurrency in Swing,其中解释了背后的原因。

教程中的SplashScreen Example执行Swing线程中的Thread.sleep。如果您在SplashScreen显示时不需要任何其他GUI刷新,这也很好。但是,您的加载代码应该在不同的线程中发生。

我建议在您的类中添加setPercent setter,创建Runnable以通过SwingUtilities.invokeLater更新GUI。这样你甚至不需要轮询percent变量,SwingThread也可以自由地呈现其他UI内容。

答案 1 :(得分:3)

Bikeshedder是对的(+1),你阻止了EDT。

while(percent <= 100) {
    System.out.println((width*percent)/100);
    g.drawRect(0, height-50, (int)((width*percent)/100), 50);
    percent += 1;
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

使用SwingUtilities.invokeAndWait((new Splash()));Runnable置于事件队列中,这意味着当您输入while循环和Thread.sleep时,您阻止事件队列调度新事件,包括重绘请求

你应该使用类似SwingWorker之类的东西来执行实际加载(在后台线程中),发布进度结果,闪屏可以显示....

enter image description here

public class TestSplashScreen {

    public static void main(String[] args) {
        new TestSplashScreen();
    }

    public TestSplashScreen() {
        SplashScreenWorker worker = new SplashScreenWorker();
        worker.execute();
        try {
            worker.get();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        System.out.println("All Done...");
//        Launch main application...
//        SwingUtilities.invokeLater(...);
    }

    public class SplashScreenWorker extends SwingWorker<Void, Float> {

        private SplashScreen splash;

        public SplashScreenWorker() {
            splash = SplashScreen.getSplashScreen();
            if (splash == null) {
                System.out.println("SplashScreen.getSplashScreen() returned null");
                return;
            }
        }

        @Override
        protected void process(List<Float> chunks) {
            Graphics2D g = splash.createGraphics();
            if (g == null) {
                System.out.println("g is null");
                return;
            }
            float progress = chunks.get(chunks.size() - 1);
            int height = splash.getSize().height;
            int width = splash.getSize().width;
            g.setComposite(AlphaComposite.Clear);
            g.fillRect(0, 0, width, height);
            g.setPaintMode();
            g.setColor(Color.WHITE);
            g.drawRect(0, height - 50, width, 50);
            g.setColor(Color.RED);
            int y = height - 50;
            g.fillRect(0, y, (int) (width * progress), 50);
            FontMetrics fm = g.getFontMetrics();
            String text = "Loading Microsoft Windows..." + NumberFormat.getPercentInstance().format(progress);
            g.setColor(Color.WHITE);
            g.drawString(text, (width - fm.stringWidth(text)) / 2, y + ((50 - fm.getHeight()) / 2) + fm.getAscent());
            g.dispose();
            splash.update();
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int value = 0; value < 1000; value++) {

                float progress = value / 1000f;
                publish(progress);
                Thread.sleep(25);

            }
            return null;
        }
    }
}