0

スプラッシュ画面で自分のプログレスバーを作成しようとしています。スプラッシュ画面の作成は簡単でした。

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

私のメインメソッドの最初の行はこれを呼び出します:

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

しかし、何も起こりません。

誰かが問題を見ることができますか?またはそれを修正する方法を知っていますか?

4

2 に答える 2

4

別のスレッドからGUIを更新する場合は、SwingUtilities.invokeLaterまたはを使用する必要があります。SwingUtilities.invokeAndWait

この背後にある理由を説明しているSwingの同時実行の章を参照してください。

チュートリアルのSplashScreenの例Thread.sleepは、Swingスレッドの内部を実行します。SplashScreenが表示されている間に他のGUIを更新する必要がない場合も、これは問題ありません。ただし、コードの読み込みは別のスレッドで行う必要があります。

を介してGUIを更新するためsetPercentのを作成するセッターをクラスに追加することをお勧めします。そうすれば、変数をポーリングする必要さえなく、他のUIも自由にレンダリングできます。RunnableSwingUtilities.invokeLaterpercentSwingThread

于 2013-02-10T21:38:13.650 に答える
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入ると、イベントキューが再描画要求を含む新しいイベントをディスパッチするのを防ぐことができます。whileThread.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;
        }
    }
}
于 2013-02-10T23:35:57.610 に答える