1

背景画像を描画してから、その上にキャラクターを描画しようとしています。私のコードは、スリープを追加するまで機能していましたが、1500 fps を取得できませんでした。

package sylvyrfysh.screen;

import javax.swing.*;
import java.awt.*;
import game.infos.Information;

public class ImageLoadDraw extends JFrame{
/**
 * 
 */
private static final long serialVersionUID = 1L;
public static void main(){
    DisplayMode dm=new DisplayMode(Information.sX,Information.sY,16,DisplayMode.REFRESH_RATE_UNKNOWN);
    ImageLoadDraw i = new ImageLoadDraw();
    i.run(dm);
}
public void run(DisplayMode dm){
    setBackground(Color.PINK);
    setForeground(Color.WHITE);
    setFont(new Font("Arial",Font.PLAIN,24));
    s=new Screen();
    try{
        loadpics();
        s.setFullScreen(dm,this);
        try{
            Thread.sleep(10000);
        }finally{
            doRun=false;
            s.restoreScreen();
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}
private void loadpics() {
    bg=new ImageIcon("src/sylvyrfysh/screen/maze_icon.png").getImage();
    chara=new ImageIcon("src/sylvyrfysh/screen/char.png").getImage();
    repaint();
}
public void paint(Graphics g){
    if(g instanceof Graphics2D){
        Graphics2D g2=(Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }
    while(true&&doRun){
        g.drawImage(bg,0,0,null);
        g.drawImage(bg,0,480,null);
        g.drawImage(bg,360,0,null);
        g.drawImage(bg,360,480,null);
        g.drawImage(bg,720,0,null);
        g.drawImage(bg,720,480,null);
        g.drawImage(chara,imgX,imgY,null);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
private Screen s;
public static int imgX=0;
private int imgY=525;
private Image bg,chara;
private Boolean doRun=true;
}

何が原因で、どのように修正するかについてのアイデアはありますか? 私が言ったように、眠らなくてもうまくいきます。

4

3 に答える 3

1

Swing はシングルスレッドのフレームワークです。以上がすべての UI インタラクションであり、変更は、再描画要求を含め、イベント ディスパッチ スレッドのコンテンツ内で実行されることが期待されます。

このスレッドの実行を停止、ブロック、またはその他の方法で妨害すると、EDT は再描画要求を含む新しいイベントを処理できなくなります。これにより、基本的に、プログラムがハングした (または応答を停止した) ように見えます。

あなたのrunメソッドでは、 を呼び出していThread.sleepます。これにより、EDT による新しいイベントの処理が停止する可能性がありますが、実際には「メイン」スレッドからメソッドを呼び出しているため、実際には機能する可能性があります...

メソッドにpaintは、無限ループとThread.sleep呼び出しがあります。paintこれらは、EDT のコンテキスト内から呼び出されるため、EDT の実行を停止します。

一部のシステムでは、paintメソッドが戻るまで、描画がすぐに行われるとは限りません。出力のためにデバイスにプッシュされない場合がありますpaint。 、とにかく悪い考えです。

他のいくつかの UI フレームワークとは異なり、「メインループ」を実装する必要はありません。Swing がこれを処理します。

代わりに、paintメソッドでは、そのサイクルでペイントする必要があるものをペイントして終了する必要があります。

代わりに、次のようなことをする必要があります...

public void paint(Graphics g){
    // Painting is a complex series of chained methods, failing to call super.paint
    // to cause significant issues
    super.paint(g);
    // Graphics is guaranteed to be an instance of Graphics2D since I think 1.4
    // You should create a copy, so any changes you make are not carried onto the
    // next component, Graphics is shared between all the components being painted
    // in this paint cycle.
    Graphics2D g2=(Graphics2D)g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.drawImage(bg,0,0,null);
    g2.drawImage(bg,0,480,null);
    g2.drawImage(bg,360,0,null);
    g2.drawImage(bg,360,480,null);
    g2.drawImage(bg,720,0,null);
    g2.drawImage(bg,720,480,null);
    g2.drawImage(chara,imgX,imgY,null);
    // If you create, you should dispose of it...
    g2.dispose();
}

...代わりは

代わりに、たとえば...Thread.sleepのようなものを利用する必要があります...javax.swing.Timer

s=new Screen();
try{
    loadpics();
    s.setFullScreen(dm,this);
    Timer timer = new Timer(10000, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            s.restoreScreen();
        }
    });
    timer.setRepeats(false);
    timer.start();
}catch(Exception e){
    e.printStackTrace();
}

詳細については、Swing での同時実行をご覧ください。

また、最上位のコンテナのオーバーライド、特に のオーバーライドを避ける必要がありますpaint。それぞれが特定のジョブを実行し、互いの上に構築されて最終結果を生成する、複雑な一連のチェーンされたメソッド呼び出しを描画します。

JPanel代わりに、たとえばから拡張したある種のカスタム コンポーネントから始めて、そのメソッドをオーバーライドし、独自のペイントを行う前にpaintComponent必ず呼び出す必要があります。super.paintComponent

詳細については、カスタム ペインティングの実行をご覧ください。

于 2013-10-23T22:22:52.270 に答える
0

loadpics()I THINK->これは、パラレルを呼び出す必要があるためです。これを試してください

public void run(DisplayMode dm){
    setBackground(Color.PINK);
    setForeground(Color.WHITE);
    setFont(new Font("Arial",Font.PLAIN,24));
    s=new Screen();
        loadpics();
        s.setFullScreen(dm,this);
        try{
            new Thread(new Runnable() {
      @Override
      public void run() {try {Thread.sleep(1000);doRun=false;s.restoreScreen();} catch (Exception e) {}
      }
    }).start();
}

doRunまた、揮発性として 設定します。private Boolean doRun=true;

于 2013-10-23T22:02:53.180 に答える