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.