2

ゲームを作成しようとしていますが、必要なすべてのファイルをロードするロード画面から始めています。完了率を表示したいのですが、うまくいきません。JPanel Loading は、Loading_files が終了した後にのみ repaints() を実行します。何が悪いのかわからない。

Main.java

package Main;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main extends JFrame{

//-------------- Final Variables --------------
//Screen Related
public final static int JFRAME_WIDTH = 800;
public final static int JFRAME_HEIGHT = 600;
public final static Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
public final static int SCREEN_WIDTH = SCREEN_SIZE.width;
public final static int SCREEN_HEIGHT = SCREEN_SIZE.height;
//Game Related
public final static String NAME = "Xubris";
public final static String IMAGE_DIRECTORY = System.getProperty("user.dir") + "\\images\\";
public static final int FPS = 1000 / 36;

//-------------- Dynamic Variables --------------
//Global
public static JFrame main;

public static void main(String[] args) {
    //Start the Loading screen
    Loading load = new Loading();

    main = new JFrame(NAME);

    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    main.setSize(JFRAME_WIDTH, JFRAME_HEIGHT);
    main.setLocation((SCREEN_WIDTH-JFRAME_WIDTH)/2, (SCREEN_HEIGHT-JFRAME_HEIGHT)/2);

    //Add Content
    main.getContentPane().add(load);

    main.setResizable(false);
    main.setUndecorated(false);
    main.setVisible(true);  
}

}

読み込み中.java

package Main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Loading extends JPanel implements Runnable{

//Pictures
BufferedImage background;

//-------------- Final Variables --------------
private final int num_of_files = 32;

//-------------- Dynamic Variables --------------
//Global Variables
private double loading_percentage = 0;
private int num_of_loaded_files = 0;

public Loading(){
    try {
        background = ImageIO.read(new File(Main.IMAGE_DIRECTORY + "Background_Loading.jpg"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    //Start the thread
    new Thread(new LoadingFiles()).start();
    new Thread(this).start();
}

public void paint(Graphics g){
    g.drawImage(background, 0, 0, this);
    for(int i = 0; i < loading_percentage; i=i+15){
        g.setColor(new Color(20,241,47));
        g.drawRect(180 + (i/15)*(50+10), 375, 50, 50);
    }
}

@Override
public void run(){
    while(true){
        repaint();
    }
}

class LoadingFiles implements Runnable{
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        num_of_loaded_files++;
        loading_percentage = (num_of_loaded_files/num_of_files)*100;

        if(num_of_loaded_files!=32)
            run();
    }

}
}
4

1 に答える 1

7

EDT をブロックし、私の最初のアイデアでも合体を再描画します (そのため、コメントに賛成票を投じました)。しかし、興味がありました-どちらも本当の問題ではありません:-)

  • どのスレッドからでも repaint を呼び出すことは完全に有効です (ただし、タイトな while ループでこれを行うと、UI の反応性が確実に低下します)。
  • いくつかのクリーンアップの後でも、期待どおりに再描画されません (以下を参照)。その原因は純粋に算数です

次の行:

loading_percentage = (num_of_loaded_files/num_of_files)*100;

これは 0 まで

num_of_loaded_files == num_of_files

つまり、すべてがロードされるまでです。私たちは皆、結論に飛びつく罪を犯しています:-)

いくつかのクリーンアップ:

  • Java の命名規則に従うと、コードが読みやすくなります
  • ペイントをオーバーライドしないで、代わりに paintComponent をオーバーライドします
  • 常に paintComponent で super を呼び出します (デフォルトでは、JPanel は不透明であるとレポートします。つまり、その領域を埋める必要があります)。
  • 絡み合ったスレッドは必要ありません。次の画像をロードした後、ロードスレッドが再描画を呼び出すだけです
  • 算数を正しくしてください:-)

コード:

public class Loading extends JPanel { 

    // Pictures
    private BufferedImage background;

    // -------------- Final Variables --------------
    private final int numOfFiles = 32;

    // -------------- Dynamic Variables --------------
    // Global Variables
    private double loadingPercentage = 0;

    private int numOfLoadedFiles = 0;

    public Loading() {
        background = XTestUtils.loadDefaultImage("moon.jpg");
        // Start the thread
        new Thread(new LoadingFiles()).start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background, 0, 0, this);
        for (int i = 0; i < loadingPercentage; i = i + 15) {
            g.setColor(new Color(20, 241, 47));
            g.drawRect(180 + (i / 15) * (50 + 10), 375, 50, 50);
        }
    }

    class LoadingFiles implements Runnable {
        @Override
        public void run() {

            while (numOfLoadedFiles < 32) {
                numOfLoadedFiles++;
                loadingPercentage = (double) numOfLoadedFiles / numOfFiles
                        * 100;
                repaint();
                try {
                    // simulate the loading
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static void main(String[] args) {
        JFrame frame = new JXFrame("", true);
        frame.add(new Loading());
        frame.setSize(600, 600);
        frame.setVisible(true);
    }
}
于 2012-08-12T09:15:43.150 に答える