2012-02-05 9 views
4

私は数時間前からプロジェクトを続けてきました。setPreferredSize()を呼び出した後、getWidth()とgetHeight()は0になります。

JPanelを追加する親JFrameがあり、開発中のシミュレーションのレンダリングと表示に使用されます。 JPanelに追加されるスイングオブジェクトはありません。これは、グラフィックスオブジェクトを使用してシェイプをレンダリングするためだけに使用されるためです。

public class SimulationPanel extends JPanel { 

private BufferedImage junction; 
private Graphics2D graphics; 

public SimulationPanel() { 
    super(); 
    initPanel(); 

} 

private void initPanel() { 
    this.setPreferredSize(new Dimension(600, 600)); //TODO: bug with not sizing the junction correctly. 
    junction = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 
    graphics = junction.createGraphics(); 
    setBackground(Color.white); 


    System.out.println(getWidth()); 
} 

コードは、特に私は新しいBufferedImageを作成しようinitPanel()メソッドの2行目に壊れる:以下のような

私のコードです。

AWT-EventQueueの-0 "スレッドの例外 "例外状態からの出力:

" java.lang.IllegalArgumentExceptionが幅(0)と高さ(0)> 0でなければならない" 私は本当にわかりませんよこれがなぜであるかについて。私は過去の答えをStack Overflowから使いこなそうとしましたが、彼らは役に立たなかった。

これは私の最初の投稿ですので、それほど悪くはないと思います。

ありがとうございました。

+0

サンプルメインを含めることはできますか?パネルが追加されたJFrameは表示されていますか? – LazyCubicleMonkey

+0

@LazyCubicleMonkeyは実際にはサンプルメインを含むことはできませんが、これは上記のJPanelが追加されたクラスです。これは明確化を助けるはずです。 http://pastebin.com/sydYnSgd –

答えて

4

好みのサイズを設定すると、コンテナに追加されたをパネルに配置する方法をさまざまなJavaレイアウトマネージャに伝えます。しかし、実際にコンテナに追加されるまでは、幅や高さはありません。また、後であっても、要求された幅と高さを持たないことがあります。

新しいバッファリングされたイメージの幅と高さには、直接600を使用するだけです。パネルをJFrameに追加するときは、JFrame上でpack()と呼んでウィンドウのサイズを優先サイズあなたのパネルの。

+0

すべてのコンポーネントをウィンドウの必要な部分に追加した後にpack()を呼び出しますが、作成しているパネルへの参照を保持する必要があります( OP)をフィールドとして扱います。つまり、私のコードでは、次のように何かを行うことはできません: contentPane.add(new SimulationPanel()、BorderLayout.CENTER); このパネルを使用するクラスがあり、この解決策を見つけるのを手助けできるかどうかを確認してください。 http://pastebin.com/sydYnSgd ありがとうございました。 –

+0

「コンテナに追加」されているだけで十分ですか?私はいつもそのコンポーネントが実現しなければならないと考えました。 – jackrabbit

+0

どういう意味ですか? –

3

コンポーネントのpaintComponentメソッド内にBufferedImageキャッシュを作成します。そこでは、コンポーネントの実際のサイズを知り、レンダリングの考慮に入れます。イメージはコンポーネントのコンテンツのキャッシュとして機能しますが、そのサイズがキャッシュされた情報の一部であることを考慮しません。

@Override protected void paintComponent(Graphics g) { 
    // create cache image if necessary 
    if (null == image || 
     image.getWidth() != getWidth() || 
     image.getHeight() != getHeight() ||) { 
    image = new BufferedImage(getWidth(), getHeight()); 
    imageIsInvalid = true; 
    } 

    // render to cache if needed 
    if (imageIsInvalid()) { 
    renderToImage(); 
    } 

    // redraw component from cache 
    // TODO take the clip into account 
    g.drawImage(image, 0, 0, null); 
} 
+0

図面のキャッシュは、私がやろうとしていることの意図です。図面はパネル自体の幅と高さに達します。そのため、パネルの幅と高さに合わせたサイズのBufferedImageを作成する必要があります。 –

+0

@DanielBond次に、 'paintComponent'の内部にキャッシュイメージを作成します。コンポーネントのサイズが変わったら、次回の 'paintComponent'の呼び出し時に新しいキャッシュイメージを作成してください。コンポーネントのサイズは、キャッシュされた状態の一部です。 – jackrabbit

+0

さて、それは物事の束をクリアします。 paintComponent(...)メソッドにすべてをダンプすることの私の主な心配は、メソッドのすべてのインスタンスで新しいキャッシュを作成することでしたが、それを十分に防ぐ方法については考えていませんでした。 ありがとうございます。 –

1

、これは動作しません理由はpack()がパネルは高さと幅がまだ設定されていない理由であるが開始された後まで(すべての幅と高さの値を設定する)と呼ばれていないということです。また、幅や高さが正の整数でない場合、BufferedImageは例外をスローします。

自分で値を設定するのはなぜですか?ここではあなたの例でそれを行う方法です:

また
private void initPanel() { 
    final int width = 600; 
    final int height = 600; 
    this.setPreferredSize(new Dimension(width, height)); 
    junction = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); 
    graphics = junction.createGraphics(); 
    setBackground(Color.white); 
} 

あなたがイメージが、あなたがする必要があるコンポーネントとサイズを変更する必要がある要件を持っている場合。私は、pack()ComponentListener.componentResized()というイベントを発生させるように呼び出されたときにはかなり確信しています。そのため、コンポーネントのサイズを変更しなくてもコンポーネントを起動すると動作するはずです。代わりにコード内でこれを実行してください:

private void initPanel() { 
    this.setPreferredSize(new Dimension(600, 600)); 

    this.addComponentListener(new ComponentListener() { 

     public void componentResized(ComponentEvent e) { 
      Component c = (Component) e.getSource(); 
      Dimension d = c.getSize(); 
      resizeImage(d); 
     } 

    }); 

    this.setBackground(Color.white); 
} 

public void resizeImage(Dimension d) { 
    junction = new BufferedImage(d.getWidth(), d.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 
    graphics = junction.createGraphics(); 
} 
+0

ありがとうございます、これはその良い実装です。私はこれを使用します。 –

関連する問題