1

2 次元の整数配列を取り、そのデータを使用して、配列で指定された配置で画面にタイルを描画するプログラムを作成しています。コードを一切変更しなくても、プログラムは 5 回中 4 回は正常に実行されます。それ以外の場合、カスタム JPanel は何も表示しません。system.out.print() をさまざまな場所に挿入した後、何も表示されていないときに paintComponent メソッドが呼び出されていないことが原因であると判断しました。明らかに、タイルが完全に表示されたときに呼び出されます。この不一致の原因を見つけることができないようです。時々ではなく、ほとんどの場合に機能するのはなぜですか?

最終的にタイルをアイソメ形式で表示するため、Isopanel と呼ばれます。0 は水タイルに相当し、1 は砂タイルに相当します。

JPanel クラス

 public class IsoPanel extends JPanel
    {
    private ArrayList <BufferedImage> tiles;
    private int[][] leveldata = 
        {
             {0,0,0,0,0,0,0,0,0,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,0,0,0,0,0,0,0,0,0}
        };
    public IsoPanel()
    {
        tiles = new ArrayList<BufferedImage>();
        tiles.add(Frame.loadImage("water.png"));
        tiles.add(Frame.loadImage("sand.png"));
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        for (int i=0; i<10; i++) 
        {
             for (int j=0; j<10; j++)
             {
              int x = j * 50;
              int y = i * 50;
              int tileType = leveldata[i][j];
              placeTile(tileType, x, y, g);
             }
        }
    }

    public void placeTile (int tile,int x,int y, Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        g2.drawImage(tiles.get(tile), null, x, y);  
    }
}

および JFrame クラス:

public class Frame extends JFrame
    {
    public Frame()
    {
        super ("Iso");
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(0,0,screenSize.width, screenSize.height);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);           
        BorderLayout bord = new BorderLayout();
        setLayout(bord);            
        IsoPanel iso = new IsoPanel();
        add(iso,BorderLayout.CENTER);
        GridLayout grid = new GridLayout(1,1);
        iso.setLayout(grid);
        iso.setVisible(true);
    }

    public static BufferedImage loadImage(String filename)
    {
        {
            try
            {
            return ImageIO.read(new File(System.getProperty( "user.dir" )+"/src/"+filename));
            }
            catch(IOException e)
            {
            }
        }
        return null;
    }

    public static void main(String[] args)
    {
        Frame one = new Frame();
    }    
}
4

1 に答える 1

3

setVisible主な問題は、子コンポーネントの初期化が完了する前にフレームを呼び出しているという事実です。これは、フレームが状態を準備する方法に関する既知の問題です...

だから、代わりに...

public Frame()
{
    /*...*/
    setVisible(true);

    /*...*/
    add(iso,BorderLayout.CENTER);
}

試す...

public Frame()
{
    /*...*/
    add(iso,BorderLayout.CENTER);

    /*...*/
    setVisible(true);
}

追加...

  • 例外を捨てるべきではありません。少なくとも、例外を出力するかログに記録する必要があります。
  • ImageObsever画像を描画するときは を使用する必要があります。の代わりにg2.drawImage(tiles.get(tile), null, x, y);、 を使用してみてくださいg2.drawImage(tiles.get(tile), x, y, this);。画像は常にすぐにレンダリングされる状態にあるとは限りません。これにより、コンポーネントが画像の状態の変化に反応し、自動的に再描画する手段が提供されます...
  • 親フレームのサイズを設定している場合でも、IsoPanelコンポーネントはオーバーライドの形式でレイアウトのヒントを提供する必要があり、メイン ウィンドウgetPreferredSizeを単純化できます。packこれにより、プラットフォームやルック アンド フィールの設定が異なるとフレーム枠のサイズが異なる可能性が低くなります。
  • 初期スレッドEventQueue.invokeLaterと、 UI を起動するために使用する重要性を確認することをお勧めします。
  • System.getProperty( "user.dir" )+"/src/"+filename)埋め込みリソースを参照する必要があるようです...
于 2013-09-19T01:10:58.613 に答える