Splash Screen Progress bar not drawing

徘徊边缘 提交于 2019-11-26 18:39:44

问题


I'm trying to make my own progress bar, on my splash screen. Creating my splash screen was easy:

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

The first line of my main method calls this:

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

And this is the splash class:

    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();
            }
        }
    }
}

I don't get any errors, but I do get a small box underneath it:

If I change the drawRects to (0, 0, width, height) it makes no difference.

I've tried invoking on the swing EDT with:

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

But nothing happens.

Can anyone see the problem? Or know how to fix it?


回答1:


You should use SwingUtilities.invokeLater or SwingUtilities.invokeAndWait when updating the GUI from a different thread.

Please see the Chapter Concurrency in Swing which explains the reasons behind this.

The SplashScreen Example from the Tutorial does the Thread.sleep inside the Swing thread. This is fine, too if you do not need any other GUI refresh while the SplashScreen is showing. Your loading code however should happen in a different thread.

I would recommend adding a setPercent setter to your class which creates a Runnable to update the GUI via SwingUtilities.invokeLater. That way you do not even need to poll the percent variable and the SwingThread is free to render other UI stuff, too.




回答2:


Bikeshedder is right (+1), you're blocking the 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();
    }
}

Using SwingUtilities.invokeAndWait((new Splash())); is placing the Runnable onto the Event Queue, meaning when you enter your while loop and Thread.sleep, you're preventing the Event Queue from dispatching any new events, including repaint requests

You should be using something like a SwingWorker to perform your actually loading (in a background thread), publishing the progress results, which the splash screen can the display....

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;
        }
    }
}


来源:https://stackoverflow.com/questions/14802662/splash-screen-progress-bar-not-drawing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!