12

最初にJFrameでレンダリングせずにJPanelからBufferedImageを作成することは可能ですか? 私は考えられる限りどこでも検索しましたが、答えが見つかりません。誰でも助けることができますか?

ここにいくつかのサンプルコードがあります。JFrame コードのコメントを外さないと、BufferedImage が空白になります。

    test(){
//      JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        Dimension dim = new Dimension(50,50);
        panel.setMinimumSize(dim);
        panel.setMaximumSize(dim);
        panel.setPreferredSize(dim);
        JLabel label = new JLabel("hello");
        panel.add(label);
//      frame.add(panel);
//      frame.pack();
        BufferedImage bi = getScreenShot(panel);

        //...code that saves bi to a jpg
    }

    private BufferedImage getScreenShot(JPanel panel){
        BufferedImage bi = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB);
        panel.paint(bi.getGraphics());
        return bi;
    }
4

2 に答える 2

8

Swingに対するこの回答を参照してください: JFrame の画像を取得する と JTable ヘッダーが画像に表示されないのはなぜですか? まだレンダリングされていないコンポーネントのペイントに関するヒントについては、問題の修正が のラベルに表示されることを期待していますLabelRenderTest.java

JLabel textLabel = new JLabel(title);
textLabel.setSize(textLabel.getPreferredSize());

アップデート

Dimension dim = new Dimension(50,50);
panel.setSize(dim);  // very important!
panel.setMinimumSize(dim);
panel.setMaximumSize(dim);
panel.setPreferredSize(dim);
// ...

または、ここに完全なソースがあります。ラベルのサイズも設定する必要があります。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class RenderTest {

    RenderTest() {
        JPanel panel = new JPanel();
        panel.setBackground(Color.RED);
        Dimension dim = new Dimension(50,50);
        panel.setSize(dim);
        panel.setMinimumSize(dim);
        panel.setMaximumSize(dim);
        panel.setPreferredSize(dim);
        JLabel label = new JLabel("hello");
        label.setSize(label.getPreferredSize());
        panel.add(label);

        BufferedImage bi = getScreenShot(panel);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
    }

    private BufferedImage getScreenShot(JPanel panel){
        BufferedImage bi = new BufferedImage(
            panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB);
        panel.paint(bi.getGraphics());
        return bi;
    }

    public static void main(String[] args) {
        new RenderTest();
    }
}
于 2012-09-19T00:25:59.760 に答える
4

EDIT2:基本的にアンドリュートンプソンは彼の答えに正しいです、フレームは必要ありません。同時に、pack()を呼び出すとレイアウトマネージャーが機能するため、これを使用するのが実用的です。元の回答の最初の部分を削除しました。左側はメモリ関連の部分です。フレームがなくても、グラフィックでdisposeを呼び出す必要があることに注意してください。

フレームを使用するときにヒープスペースが不足することについて:これは発生しないはずです。おそらく、フレームを使い終わったら、フレームでdispose()を呼び出すだけで済みます。それでも問題が解決しない場合は、別の質問で質問することをお勧めします。廃棄ドキュメントから:

このウィンドウ、そのサブコンポーネント、およびその所有するすべての子によって使用されるすべてのネイティブ画面リソースを解放します。つまり、これらのコンポーネントのリソースは破棄され、それらが消費するメモリはすべてOSに戻され、表示不可としてマークされます。(...)注:Java仮想マシン(VM)内の最後の表示可能なウィンドウが破棄されると、VMが終了する場合があります。

編集:もう少し考え:

  • 同じJFrameオブジェクトを再利用することも機能するはずです。パネルの追加、パックの呼び出し、画像の作成、パネルの削除、繰り返し
  • 自分で作成したグラフィックスオブジェクトでもdispose()を呼び出すことを忘れないでください
  • 最悪の場合、スクリプトからJVMを時々再起動できます
于 2012-09-18T17:35:28.947 に答える