简体   繁体   中英

Splash Screen Progress bar not drawing

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?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM