私はその場で生成するJPEGとPNG画像を追加したいと思う JPanel を持っています。
これまでに Swingチュートリアル で見たすべての例、特に Swingの例 ではImageIcon
sを使用しています。
私はこれらの画像をバイト配列として生成していますが、通常は例で使用されている一般的なアイコンよりも大きい640 x 480です。
編集 :チュートリアルとAPIをもっと慎重に調べると、ImageIconを直接JPanelに追加できないことがわかります。代わりに、それらはJLabelのアイコンとして画像を設定することによって同じ効果を達成します。これはちょうどいい感じではありません...
これが私のやり方です(画像のロード方法についてもう少し詳しく説明します)。
import Java.awt.Graphics;
import Java.awt.image.BufferedImage;
import Java.io.File;
import Java.io.IOException;
import Java.util.logging.Level;
import Java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters
}
}
あなたがJPanelsを使用しているなら、おそらくSwingを使用しています。これを試して:
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);
画像は今スイングコンポーネントです。他のコンポーネントと同様にレイアウト条件の影響を受けます。
Fred Haslamの方法はうまくいきます。私は私のjarファイル内の画像を参照したいので、私はしかし、ファイルパスに問題がありました。これを行うために、私は使用しました:
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));
この方法でロードする必要があるのは有限個(約10個)の画像しかないので、それは非常にうまく機能します。正しい相対ファイルパスを指定せずにファイルを取得します。
サブクラス化する必要はないと思います。 Jlabelを使うだけです。画像をJlabelに設定できます。そのため、Jlabelのサイズを変更してから画像を埋めます。大丈夫です。これが私のやり方です。
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
ImageIcon
sを使用します。単一の画像の場合は、JPanel
のカスタムサブクラスを作成し、そのpaintComponent
メソッドをオーバーライドして画像を描画することを考えます。JPanelをサブクラス化することができます - これは私のImagePanelからの抜粋です。これは上/左、上/右、中央/中央、下/左または下/右の5つの場所のいずれかに画像を置きます。
protected void paintComponent(Graphics gc) {
super.paintComponent(gc);
Dimension cs=getSize(); // component size
gc=gc.create();
gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2) +mmHrzShift),(((cs.height-mmSize.height)/2) +mmVrtShift),null); }
if(tlImage!=null) { gc.drawImage(tlImage,(insets.left +tlHrzShift),(insets.top +tlVrtShift),null); }
if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top +trVrtShift),null); }
if(blImage!=null) { gc.drawImage(blImage,(insets.left +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
}
JPanel
はほとんどの場合サブクラスにとって間違ったクラスです。なぜあなたはJComponent
をサブクラス化しないのですか?
ImageIcon
には、コンストラクタが画像の読み込みをブロックするという点でわずかな問題があります。アプリケーションjarから読み込むときにはそれほど問題ではありませんが、ネットワーク接続を介して読んでいる可能性がある場合はおそらくそうです。 JDKのデモでも、MediaTracker
、ImageObserver
、および友人を使用するAWT時代の例はたくさんあります。
私が取り組んでいるプライベートプロジェクトでも、非常によく似たことをしています。これまで私は問題なく(メモリを除く)最大1024 x 1024の画像を生成していて、パフォーマンス上の問題もなく非常に素早くそれらを表示することができます。
JPanelサブクラスのPaintメソッドをオーバーライドするのはやり過ぎであり、あなたがする必要があるよりも多くの作業を必要とします。
やり方は次のとおりです。
Class MapIcon implements Icon {...}
OR
Class MapIcon extends ImageIcon {...}
画像を生成するために使用するコードはこのクラスになります。 paintIcon()が呼び出されたときに描画するためにBufferedImageを使用します。g.drawImvge(bufferedImage)を使用します。これにより、画像を生成している間に行われる点滅の量が減り、スレッド化することができます。
次にJLabelを拡張します。
Class MapLabel extends Scrollable, MouseMotionListener {...}
これは、スクロールペインに画像を配置したいためです。画像の一部を表示し、必要に応じてユーザーにスクロールさせます。
そこで私は、MapIconだけを含むMapLabelを保持するためにJScrollPaneを使います。
MapIcon map = new MapIcon ();
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);
しかしあなたのシナリオでは(ちょうど毎回全体の画像を見せる)。 MapLabelを一番上のJPanelに追加し、それらをすべて画像のフルサイズに合わせるようにする必要があります(GetPreferredSize()をオーバーライドすることによって)。
プロジェクトディレクトリにソースフォルダを作成します。この場合は、Imagesと呼びます。
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();
この答えは@ shawalliの答えを補完するものです...
私は私のjarファイル内でも画像を参照したいのですが、BufferedImageを持っているのではなく、これを単純にしました。
JPanel jPanel = new JPanel();
jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));
あなた自身のComponent
sとSwingXライブラリとImageIO
クラスの使用を避けることができます:
File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));
私は多くの答えを見ることができますが、実際にはOPの3つの質問に対処するわけではありません。
1) パフォーマンスに関する言葉:あなたのディスプレイアダプタの現在の解像度と色深度に一致する正確なピクセルバイト順を使用できない限り、バイト配列はおそらく非効率的です。
最高の描画パフォーマンスを実現するには、画像を現在のグラフィック構成に対応する型で生成されたBufferedImageに変換するだけです。 https://docs.Oracle.com/javase/tutorial/2d/images/drawonimage.html にあるcreateCompatibleImageを参照してください。
プログラミングの手間をかけずに数回描画した後、これらの画像は自動的にディスプレイカードのメモリにキャッシュされるので(これはSwingではJava 6以降の標準です)、したがって実際の描画にはごくわずかな時間がかかります - ifあなたは画像を変えませんでした。
イメージを変更すると、メインメモリとGPUメモリの間で追加のメモリ転送が発生します。これは時間がかかります。そのため、画像をBufferedImageに「再描画」することは避け、getPixelおよびsetPixelを絶対に行わないでください。
たとえば、ゲームを開発している場合、すべてのゲームアクターをBufferedImage、次にJPanelの順に描画するのではなく、すべてのアクターを小さいBufferedImageとしてロードし、それらを1つずつJPanelコードに描画する方がはるかに高速です。それらの適切な位置 - このように、キャッシュのための画像の初期転送を除いて、メインメモリとGPUメモリとの間の追加のデータ転送はありません。
ImageIconは内部でBufferedImageを使用します - しかし基本的にproperグラフィックモードでBufferedImageを割り当てることが重要であり、これを正しく行う努力はありません。
2) これを行う通常の方法は、JPanelのオーバーライドされたpaintComponentメソッドでBufferedImageを描画することです。 Javaは、GPUメモリにキャッシュされたVolatileImagesを制御するバッファチェーンなど、その他にも豊富な機能をサポートしていますが、Java 6以降、これらのGPUアクセラレーションの詳細を一切公開せずに適切な処理を行う必要はありません。
GPUアクセラレーションは半透明の画像を引き伸ばすなどの特定の操作では機能しない場合があることに注意してください。
3) 追加しないでください。上記のようにペイントするだけです。
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
画像がレイアウトの一部である場合、「追加」は意味があります。 JPanelを塗りつぶす背景画像または前景画像としてこれが必要な場合は、単にpaintComponentを描画します。あなたのイメージを表示することができる一般的なSwingコンポーネントを作りたいなら、それは同じ話です(あなたはJComponentを使って、そのpaintComponentメソッドをオーバーライドすることができます) - そしてGUIコンポーネントのレイアウトにthisを加えます。
4) 配列をバッファ画像に変換する方法
あなたのバイト配列をPNGに変換してそれをロードすることは非常にリソース集約的です。もっと良い方法は、既存のバイト配列をBufferedImageに変換することです。
そのためには:ループには使用しないでくださいそしてピクセルをコピーしてください。それはとてもとても遅いです。代わりに: