2013-10-23 3 views
1

나는 그 위에 문자를 그리는 배경 이미지를 그리려하고있다. 수면을 추가 할 때까지 내 코드가 작동하고 있었는데 1500fps를 얻지 못했습니다.이미지 잠자기 후 그림을 그리기 자바

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; 
} 

문제의 원인과 해결 방법에 대한 아이디어가 있습니까? 내가 말했듯이, 잠도없이 잘 작동합니다.

+1

당신이 바로, 당신이 10 초 동안 잠을자는 실현을위한 Performing Custom Painting에서보세요? – Doorknob

+1

그리고 끝없는 루프에 의해 50 밀리 초로 일시 중지되었습니다. – mKorbel

+0

나는 창을 10 초 동안 열어 두었습니다. 그리기 루프는 마지막 코드 블록이며 0.05 초 타이머로 설정됩니다. – johnnic431

답변

1

스윙은 단일 스레드 프레임 워크입니다. 즉, 모든 UI 상호 작용 및 수정은 다시 발송 요청을 포함하여 이벤트 발송 스레드의 콘텐츠 내에서 실행될 것으로 예상됩니다.

이 스레드를 정지, 차단 또는 달리 실행하지 못하게하면 EDT가 다시 이벤트를 처리하는 데 방해가됩니다. 이것은 본질적으로 프로그램이 중단되었거나 응답하지 않은 것처럼 보일 것입니다.

run 방법에서는 Thread.sleep으로 전화하고 있습니다. 이것은 EDT가 새로운 이벤트를 처리하는 것을 막을 가능성이 있지만, 실제로 "메인"스레드에서 메서드를 호출했기 때문에 실제로 작동 할 수도 있습니다. 그러나 ...

paint 메서드에서는 무한 루프가 있습니다. 및 Thread.sleep 전화. 이것들은 EDT의 문맥 안에서 paint이 호출되기 때문에 EDT가 실행되는 것을 멈추게 할 것입니다.

회화 항상 그 사실에 관계없이의 paint 내에서 루프의 경우에도 아이디어를 paint 메소드가 복귀 할 때까지,이 출력 장치에 푸시 할 수 없습니다, 일부 시스템에 즉시 발생하므로하지 않습니다 EDT에 문제가 발생할 것입니다. 나쁜 생각입니다.

다른 UI 프레임 워크와 달리 "메인 루프"를 구현할 필요가 없으며 스윙이이를 처리합니다.

대신 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(); 
} 

은 자세한 내용은 Concurrency in Swing를 살펴 보자.

또한 최상위 컨테이너를 무시하고 특히 paint을 무시하지 않아야합니다. 일련의 복잡한 일련의 메소드 호출을 페인팅합니다. 각 메소드는 특정 작업을 수행하며, 서로의 위에 쌓여 최종 결과를 생성합니다.

대신에, 당신은 당신의이 그림을 소유하기 전에 당신이 super.paintComponent 전화를 확인하는, 예를 들어 JPanel에서 연장, 어떤 종류의 사용자 지정 구성 요소로 시작하고 paintComponent 메소드의 오버라이드 (override) 할 필요가 있습니다.

은 자세한 내용

+0

+1, 죄송합니다. 이미 오래 전에 저에게 문제를 설명해 주셨습니다. :) – Sage

0

그럼이 하나 Thread.sleep(10000);은 10 초 동안 꺼져 있습니다. 이것은 당신이 원하는 것이 아닙니다. 심지어 30 밀리 초 (30frames/sec)로하는 것조차도 입력이 멈추기 때문에 원하는 것이 아닙니다.

타이머를 사용해야합니다. 그것은 다른 스레드에서 타이밍을 실행하고 잠자기 및 해당 스레드가 자동으로 지정된 수의 밀리 초 수 있으므로 프로그램에 영향을 미치지 않으며 예를 들어 30 밀리 초 후에 만 ​​호출 할 수 있습니다. 아직

이 타이머가 낮은 값을 가져야한다, 좋은 응용 프로그램을하고 당신은 그러나

내가 THINK-
0

>이는 각 5milisec 등의 입력을 읽어 System.nanoTime()을 통과하는 시간을 계산하고, 예를 들어 한 번 각 30milisec을 다시 칠해야 당신이 loadpics() 평행하게 호출 할 필요가 있기 때문에,이

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;

+0

@downvoter 자신을 증명해주십시오. –

+0

다운 voter가 아니라 EDT 외부의 Swing 구성 요소와의 상호 작용은 나쁜 생각이며 OP가 커밋하는 최악의 범죄는 아닙니다. 스레드가 인터럽트되면,'doRun'과's.restoreScreen'은 절대로 호출되지 않을 것입니다 ... – MadProgrammer

+0

@MadProgrammer 좋은 지적이지만, 여기 스레드를 방해하는 것은 99.9 %입니다. 그리고 부름 방법에 관해서는 그렇게 열심히하지는 마라. 단지 finally 블록이 필요하다. 우리는 정확한 것을 제외하고는 안된다. –

관련 문제