2011-01-09 3 views
5

프레임 안에 JPanel이 있습니다. JPanel의 내용은 paintComponent (repaint()이 호출 됨)을 호출 할 때마다 업데이트 될 예정이지만, 아래에 나와있는 것처럼 흰색 창이 나타납니다. 은 (이클립스 탭 이상한 물건의 모든 종류의 수행, 난도질 들여 쓰기를 용서하시기 바랍니다.)프레임 안의 JPanel 다시 칠하기

private static void handleGUI() 
{  
    JFrame frame = new JFrame("Animation"); 
    frame.setPreferredSize(new Dimension(100, 100)); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    Board b = new Board(); 

    frame.getContentPane().add(b); 

    frame.pack(); 
    frame.setVisible(true); 

    while(true) 
    { 
     System.out.println("Repainting panel"); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
     } 
     b.repaint(); 
    } 
} 

public class Board extends JPanel 
{ 
public Board() { t=0; } 

    private int t; 

public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g); 

    ++t; 

    /* Variables snipped */ 

    g.setColor(Color.white); 
    g.drawOval(0, 0, width, height); 

    BufferedImage image = ImageIO.read(new File(imagePath)); 
    g.drawImage(image, x(t), y(t)); 
    /* There's some more image and rectangle drawing ahead */ 
} 

}

+2

실제로 이클립스는 모든 종류의 멋진 탭을 제공합니다. :-) CTRL-SHIFT-F를 눌러 소스를 자동으로 포맷하십시오. 일관된 형식 및 들여 쓰기가 만들어 지므로 직접 수행하는 부담을 덜어줍니다. – harschware

+0

x (0), y (0)의 값은 무엇입니까? 이미지가 패널 외부에있을 수 있습니다. 디버거에서 실행합니까? 이미지를 찾을 수없는 경우 코드가 GUI 스레드에서 예외를 throw 할 수 있습니다. – josefx

답변

6

코드에 몇 가지 문제가 있습니다. 하나는 위에서 언급 한 것입니다. (1+ 담당자 - 드로잉을 수행하는 paintComponent 메소드에 코드가있는 것처럼 보이지만 paintComponent 메소드에 결함이 있습니다. 하지만 그뿐만 아니라 Swing 메인 스레드 인 EDT에서 while (true) 루프와 Thread.sleep을 얻었습니다. 그러면 EDT가 Swing과 전체 GUI를 잠자기 상태로 만듭니다. 대신 스윙 타이머를 사용하는 것이 좋습니다. 또한, 당신은 인 JPanel의 내용은 (재 페인트에 의해 호출())의 paintComponent를 호출 할 때마다,

당신이 넣어 하시겠습니까으로 업데이트로되어있다

, 상태 paintComponent 메소드 내부의 프로그램 로직? 이것은 보통 프로그래머가이 메소드가 호출되는 시점에 관해 완전한 제어권을 갖고 있지 않으므로 frowned된다. 다시 그리기를 호출 할 때 호출 될 수 있지만 (항상 그런 것은 아닙니다), 호출 할 것으로 예상하지 않을 때 OS의 메시지로 인해 호출 될 수 있습니다.

또한 paintComponent 메소드 내부의 파일을 읽지 않으려 고하므로 페인트가 걸림돌이 될 수 있습니다. 이미지가 어떤 의미가 있는지

1) 1000의 기간과 스윙 타이머를 생성하고 이미지에 읽었다의 ActionListener의 actionPerformed 메소드에서 (바람직하게는 백그라운드 스레드에서 :

나는 이러한 변경 사항을 권 해드립니다 크기) 이미지를 클래스 필드 (예 : 이미지)에 읽어들입니다.

2) 동일한 Timer의 actionPerformed 메서드에서 t를 증가시킵니다.

3) 이미지를 읽은 후 드로잉 JPanel에서 repaint를 호출하고 JPanel에서 이미지 변수를 사용하여 이미지를 페인트합니다. 배경 스레드를 사용하여 이미지를 읽을 때 이미지가 완전히 읽혀 졌을 때이 스레드에 GUI에 알릴 필요가 있으므로주의해야합니다. SwingWorker를 사용하여 이것을 수행하는 경우에는 수신 대기하는 PropertyChangeListener를 추가 할 수 있습니다 이 값이 SwingWorker의 상태 값으로 변경되고이 값이 StateValue.DONE으로 변경되면 트리거됩니다.

이 내용이 분명하지 않거나 혼란 스럽다면 명확히해야합니다.

편집 : 이미지가 너무 크면 한 번에 모두 읽을 수도 있고, 묶음이 필요할 때 일괄 적으로 읽을 수도 있습니다. 이미지를 사용하기 직전에 이미지를 읽을 필요가 없습니다.

1

당신의 paintComponent에 그냥 super.paintComponent를 호출합니다. 따라서 JPanel은 자체적으로 페인트를 칠하면서 밝은 회색 또는 흰색 또는 밝은 갈색 또는 모양과 느낌에 따라 다릅니다.

+0

잠이 들었을 때 그의 앱이 잠겨서 모든 페인트를 끝내지 않았기 때문에 아마 흰색 일 것입니다. – harschware

2

스레드를 잠자기 상태로 설정하지 마십시오. 스윙 타이머를 사용하여 페인트 이벤트를 해제하십시오.