質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Q&A

解決済

3回答

2858閲覧

ダブルバッファリングしたら重くなりました

rimokonTenko_mo

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

0グッド

1クリップ

投稿2020/03/26 14:46

編集2020/03/27 15:06

Swingを使って2Dスクロールゲームを作るときに、ダブルバッファリングを実装したのですが、バッファイメージのサイズを大きくすると動きが遅くなってしまいました。以下はその詳細です。何か分かることがございましたら、アドバイスをお願いします。

#ダブルバッファリング実装方法
クラス[変数名]
JFrameにおいてインスタンス生成時に、createImage(this.getWidth(), this.getHeight())でバッファイメージImage[back]back.getGraphics()でそのグラフィクスGraphics[buffer]を変数として取得しておく。
・paint(Graphics g)をオーバーライドして
buffer
に描画して、最後に**graphics.drawImage(back, 0, 0, this)**でバッファイメージを描画する。
・componentResizedをオーバーライドしてImage[back]Graphics[buffer]を変更(更新)する。
・update(Graphics g)はオーバーライドしていない。

#問題点
・実行してみて、画面を大きくすると動きが遅くなることに気がついた。
・フレームレートを測定すると、画面の大きさに比例して時間が遅くなっていた。
・試しに、**graphics.drawImage(back, 0, 0, this)**だけをコメントアウトすると画面は変わらないが、フレームレートは速くなった。
・試しに、**paint(Graphics g)において、先頭でbuffer = g;を書くと(ダブルバッファリングしないようにすると)ちらつくが速くなった。
・試しに、インスタンス生成時に
createImage(2000, 2000)**とするとずっと遅くなった。

#修正(該当のコード)

java

1package orgmarigo.test; 2 3import javax.swing.*; 4import java.awt.Graphics; 5import java.awt.Image; 6import java.awt.event.*; 7 8import orgmarigo.util.Vector2; 9import orgmarigo.util.TimeMeasure;//フレームレートを測定するクラス 10import orgmarigo.util.MyUtilities; 11 12public class ScreenTest extends JFrame implements ActionListener, ComponentListener{ 13 static public final Vector2 INITIAL_WINDOW_SIZE = new Vector2(630, 560); 14 static public TimeMeasure timeMeasure = new TimeMeasure(100); 15 static public final int FPS = 100; 16 17 private Timer timer; 18 private Image back; 19 private Graphics buffer; 20 private Image titleImage; 21 22 public static void main(String[] args) { 23 new ScreenTest(); 24 } 25 26 public ScreenTest(){ 27 this.setTitle("ScreenTest"); 28 this.setBounds(300, 200, (int)INITIAL_WINDOW_SIZE.getX(), (int)INITIAL_WINDOW_SIZE.getY()); 29 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 30 31 this.addComponentListener(this); 32 33 this.setVisible(true); 34 35 timer = new Timer(1000 / FPS, this); 36 back = createImage(this.getWidth(), this.getHeight());//バッファイメージ 37 buffer = back.getGraphics();//イメージのグラフィクス 38 titleImage = MyUtilities.getImage("../images/title/TitleImage.jpg"); 39 40 timer.start(); 41 } 42 43 @Override 44 public void paint(Graphics graphics){ 45 if(buffer != null){ 46 //イメージの更新、描画 47 buffer.clearRect(0, 0, this.getWidth(), this.getHeight()); 48 buffer.drawImage(titleImage, 0, 0, this.getWidth(), this.getHeight(), null); 49 } 50 51 graphics.drawImage(back, 0, 0, this); 52 } 53 54 @Override 55 public void actionPerformed(ActionEvent e){ 56 Object source = e.getSource(); 57 58 if(source == timer){ 59 timeMeasure.Update(); 60 repaint();//再描画 61 } 62 } 63 64 @Override 65 public void componentHidden(ComponentEvent e) {} 66 67 @Override 68 public void componentMoved(ComponentEvent e) {} 69 70 @Override//リサイズしたとき 71 public void componentResized(ComponentEvent e) { 72 back = createImage(this.getWidth(), this.getHeight()); 73 buffer = back.getGraphics(); 74 } 75 76 @Override 77 public void componentShown(ComponentEvent e) {} 78}

#その他
・ネットで調べて、setDoubleBuffered(boolean)を見つけたが使い方がわからなかった。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ダブルバッファの目的は、ユーザビリティの向上であり、データを集めている間にすでに集まっているデータを利用して処理をすることで、ユーザの応答性が向上することが主な目的になります。並行して処理を行うことにより返って処理が重くなることはあり得る問題です。

画面を大きくすると動きが遅くなる

画面サイズによりということは、例えば画素単位での処理がある場合に処理が増大したりしますし、バッファサイズに影響を与えている可能性もあります。

画面の大きさに比例して時間が遅くなっていた

これも一フレームあたりの処理が遅くなるためでしょう。

graphics.drawImage(back, 0, 0, this)だけをコメントアウトすると画面は変わらないが、フレームレートは速くなった

drawImage自体は描画を行うが、画像サイズに比例して描画時間が増大することは考えられなくは無いですね。

ですので、一画面の処理をある程度高速化するなりしないと改善が難しいと思いますし、それをするためには、その処理のパフォーマンス測定、プロファイルが必要かと思います。
また、その速度が十分に高速になれば、ダブルバッファも不要になるかもしれません。

投稿2020/03/27 05:33

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

実メモリー不足では?
実装されているメモリーに対し、アプリが使用するメモリー量が多すぎると、ページングと言ってその時点で使用していないメモリーの一部を一時的にディスクに書き出して実メモリー不足を補って処理します。
これが多発すると処理速度が目に見えて落ちます。
ダブルバッファーとすることでメモリー不足が発生している可能性があります。
メモリー量(実装量と、アプリが動作する前の時点でのOS等の使用量、アプリの使用量)を確認してください。

投稿2020/03/27 05:00

sage

総合スコア1216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

バッファイメージのサイズを大きくすると動きが遅くなってしまいました。

ダブルバッファリングも"処理"ですから, 対象が多くなれば遅くなるのは当然かと思います.
ダブルバッファリングのコードの問題とお考えであれば, 「JFrameにおいてインスタンス生成時に~」という日本語説明で無く, コードをご提示ください.

setDoubleBuffered(boolean)を見つけた

Swing はコンポーネントの描画の為にダブルバッファリングを(うろ覚えですが) JComponent のレベルで実装・実行しています.
ただ個々のコンポーネントがダブルバッファリングしても意味はありませんので, 個々のコンポーネントのデフォルトは Off となっており, JFrame の ContentPane のレベルが On になっています.
その On/Off を設定するためのメソッドが setDoubleBuffered だったと思います.

投稿2020/03/27 01:15

jimbe

総合スコア12612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rimokonTenko_mo

2020/03/27 09:57

コードは、どう言う形で提示すればよいでしょうか。 質問に関係のある処理以外にもいろいろな処理が書かれていて、ファイル全体を提示すればよいのか、あるいは必要な部分だけ切り取って提示すればよいのか分かりません。
jimbe

2020/03/27 10:16

可能であれば全体が良いですが, 推奨最低条件は「コンパイルして状況が再現できる」コードです.
rimokonTenko_mo

2020/03/27 15:08

再現するのに少し時間がかかってしまいましたが、コードを提示しました。よろしくおねがいします。
jimbe

2020/03/28 00:10

orgmarigo.util.* や大きな jpeg が必要なので試せませんが, このコードはダブルバッファリングがどうこうというよりは, 単にベタ画像を書くのにどれだけ時間が掛かるかというだけではないでしょうか. ダブルバッファリングの一番の目的は, 消したり書いたりによるちらつきを無くすことです. バッファ(メモリ領域)を用いたりバッファへの書き込み→画面への書き込みという段階を踏んだりの余計な資源・時間を使うこととのトレードオフでダブルバッファリングを行うか否かを判断すべきで, つまりちらついても早いほうが良いか, 遅くてもちらつかないほうが良いかです. もし画面のほとんどが時間が経っても変わらず, フレーム毎のバッファへの更新範囲が少ないなら, バッファから画面への描画も更新範囲のみに最適化することで高速化は出来ますが, ご提示のコードではそれが出来るかは分かりません. 2Dスクロールゲームということですので, ゲーム中は背景全体がスクロールしているとしたら, 部分更新による高速化は出来ないかもしれませんので, 「遅くてもちらつかない」ということで仕方ないとするしかないかもしれません.
rimokonTenko_mo

2020/03/30 03:16

分かりました。最初は、paint関数の引数も、バッファイメージも同じGraphicsなのに、なぜ遅くなるんだろうと思っていたのですが、2つのGraphicsは何か違うみたいですね。問題の「重くなった」のは、ダブルバッファリングの「代価」ということですか。エラーみたいに何かを追加したり、文法が間違っているといった問題ではなく、仕方がないものであるということがわかって、良かったです。ウィンドウのサイズを固定化するなどして対応してみます。
jimbe

2020/03/30 04:20

> paint関数の引数も、バッファイメージも同じGraphicsなのに、なぜ遅くなるんだろうと思っていた 同じなのは「出来ることが同じ」だからで, 作用する先が違うということです. 同じペンを使っても, 役所への提出資料にも広告の裏にも書けるのと同じです. ダブルバッファリングにつきましては多数情報があると思いますので, 再度確認・調査されたらと思います.
rimokonTenko_mo

2020/03/30 06:22

丁寧に教えていただき、ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問