我正试图在我的启动画面上创建自己的进度条。创建我的启动画面很简单:
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();
}
}
}
}
我没有收到任何错误,但我确实在它下面放了一个小盒子:
如果我将drawRects更改为(0,0,width,height),则没有任何区别。
我已尝试使用以下方式调用EDT:
SwingUtilities.invokeAndWait((new Splash()));
但没有任何反应。
有人能看到问题吗?或者知道如何解决它?
答案 0 :(得分:4)
从其他线程更新GUI时,您应该使用SwingUtilities.invokeLater
或SwingUtilities.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
之类的东西来执行实际加载(在后台线程中),发布进度结果,闪屏可以显示....
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;
}
}
}