2017-09-27 4 views
0

두 가지 페인트 방법을 사용하여 이전 "페인트"방법으로 생성 된 "그림"을 기반으로 출력을 만드는 프로그램을 작성했습니다. draw1과 draw2의 두 가지 메소드가 있으며, 초기 구성은 draw1을 사용하여 주어진 다음 draw2는 다음 행의 출력을 생성하는 데 사용됩니다. 그러나 코드를 실행할 때 정의 된 메서드가 호출되는 순서와 관련하여 이상한 오류가 발생합니다. 이 코드를 이해하기 위해 여러 개의 print() 문을 코드에 추가했지만 print() 문을 추가하면 메서드 호출 자체에 영향을주는 것으로 보아 문제가 심각해질뿐입니다. 이 코드를 실행하면모호하고 일관성없는 순서의 메서드 호출

import java.awt.*; 
import java.awt.Color; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import java.awt.image.BufferedImage; 

public class Processor extends JFrame 
{ 
static int x=1; 
public Processor() 
{ 
    setTitle("Automaton"); 
    setSize(1000,1000); 
    setVisible(true); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    System.out.println("In constructor"); 
} 

public void paint(Graphics g) 
{ 
    if(x==1) 
     draw(g); 
    else if(x==2)  
     draw2(g);   
} 

public void draw(Graphics g) 
{ 
    g.setColor(Color.WHITE); 
    g.fillRect(0,0,1000,1000); 
    System.out.println("In Draw"); 
}//This is the initial setting. 

public void draw2(Graphics g) 
{ 
    g.setColor(Color.BLACK); 
    g.fillRect(500,22,50,50); 
    System.out.println("In Draw2"); 
} 

public static BufferedImage toBufferedImage(Component component) 
{ 
    BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB); 
    Graphics g = image.getGraphics(); 
    component.paint(g); 
    return image; 
} 

public static void main(String[]args) 
{ 
    System.out.println("Start"); 
    BufferedImage image; 
    Processor t=new Processor(); 
    System.out.println("Middle"); 
    image=toBufferedImage(t); 
    System.out.println("End"); 
    //Color myColor=new Color(image.getRGB(500,500)); 

    x=2; 
    image=toBufferedImage(t); 
} 

} 

, 나는 빈 흰색 화면 -

Start 
In Draw 
In constructor 
Middle 
In Draw 
In Draw 
End 
In Draw2 

두와 함께 다음과 같은 출력을 얻을 - 여기

은 (여전히 아주 기본 버전) 코드입니다 질문에서 내 마음에 와서이

1)

image=toBufferedImage(t); 
의 실행을 수행하는 이유

draw()가 두 번 호출됩니까?

2) "In draw2"행에서 알 수 있듯이 프로그램이 draw2()를 입력했습니다. 그런데 왜 내가 빈 화면을 볼 수 있을까? (사각형 제외).

또 다른 print() 문을 추가하려고하면 메서드 호출 순서가 변경됩니다. 질문의 과도한 길이 때문에 코드와 출력을 추가하지는 않았지만 이에 대한 설명이 있는지 알고 싶습니다.

P.S 코드를 실행하는 데 BlueJ Environment를 사용하고 있습니다.

+0

디버거를 사용하여 코드 실행을 단계별로 시도 했습니까? –

+0

"public void paint (Graphics g)"메서드는 이미 JFrame (java.awt.Window에 의해)에 정의되어 있으며 의도에 의해 재정의합니까? - 적어도 "setVisible (true)"호출이 "paint (Graphics g)"를 호출하기 때문에 "Draw"가 "Start"다음에 직접 인쇄되는 이유입니다. – SWoeste

+0

@SWoeste 의도적으로 페인트를 오버라이드했습니다. 의견을 보내 주셔서 감사합니다. 퍼즐의 한 부분이 해결되었습니다. 그러나, 내가 정말로 알고 싶은 것은 draw()가 (출력이 두 번 올 것이라고 제안 된 것처럼) 어떻게 호출 할 수 있었는지입니다. –

답변

0

어디에서 메서드가 호출되었는지 알고 싶다면 쉽게 속임수가 있습니다. 이런 식으로 당신에게 paint 방법을 변경 : 여기

내 실행 중 하나의 출력 :

public void paint(Graphics g) 
{ 
    System.out.println("paint called from " + Thread.currentThread().getName()); 
    new Exception().printStackTrace(System.out); 
    if(x==1) 
     draw(g); 
    else if(x==2)  
     draw2(g);   
} 

출력은 호출이 toBufferedImage에서하지만 스레드에서 오는되지 않는다는 것을 당신에게 말할 것이다 AWT-EventQueue-0라는

Start 
In constructor 
Middle 
paint called from AWT-EventQueue-0 
java.lang.Exception 
    at Processor.paint(Processor.java:22) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718) 
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744) 
    at java.awt.EventQueue.access$400(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:697) 
    at java.awt.EventQueue$3.run(EventQueue.java:691) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 
In Draw 
paint called from main 
java.lang.Exception 
    at Processor.paint(Processor.java:22) 
    at Processor.toBufferedImage(Processor.java:47) 
    at Processor.main(Processor.java:57) 
In Draw 
End 
paint called from main 
paint called from AWT-EventQueue-0 
java.lang.Exception 
    at Processor.paint(Processor.java:22) 
    at Processor.toBufferedImage(Processor.java:47) 
    at Processor.main(Processor.java:62) 
In Draw2 
java.lang.Exception 
    at Processor.paint(Processor.java:22) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718) 
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744) 
    at java.awt.EventQueue.access$400(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:697) 
    at java.awt.EventQueue$3.run(EventQueue.java:691) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 
In Draw2 
paint called from AWT-EventQueue-0 
java.lang.Exception 
    at Processor.paint(Processor.java:22) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718) 
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744) 
    at java.awt.EventQueue.access$400(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:697) 
    at java.awt.EventQueue$3.run(EventQueue.java:691) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 
In Draw2 

BTW : 놓친 사각형을 볼 수 있습니다.

+0

아주 좋은, 고마워! 나는 AWT의 초심자 였고 시스템이 이러한 호출을 자체적으로 생성했는지 알지 못했습니다. –

0

두 스레드 (EventDispatchThreadmain 스레드)에서 draw 메서드를 실행하고 있습니다.

피하려면 생성자에서 setVisible(true)을 호출하지 말고 나중에 main()에서 호출하십시오.

0

페인팅 코드가 잘못되었습니다.

  1. JFrame의 paint()를 재정의하지 마십시오. 그러나 만약 당신이 그렇게한다면, 적어도 페인트를 제대로하기 위해서는 super.paint()가 필요합니다.

  2. 페인팅은 JPanel에서 paintComponent (...)를 오버라이드하여 수행됩니다. 그런 다음 프레임에 패널을 추가합니다.

  3. 페인트 (...)를 직접 호출하지 마십시오. 스윙은 Graphics 객체를 만들고이를 paint() 메소드에 전달합니다. 대신 구성 요소에서 repaint()를 호출합니다.

그래서 그림이 잘못되었다는 것을 제외하고는 무슨 일이 일어나고 있는지에 대한 어떠한 질문도 대답 할 수 없습니다. 그래서 그림을 제대로하고 불일치가 사라질 것이라고 확신합니다.

+0

큰 피드백, 감사합니다! 사실, 아직 AWT와 Swing을 자바로 작업하는 초보자입니다. 나는 그것이 AWT가 어떻게 작동하는지 약간의 이해를 얻을 수 있도록 단순히 AWT로 놀고 있었다. 내가 가지고있는 또 다른 질문은 - 내 프로그램에서 내가 이미 가지고있는 그림을 바탕으로 다음 "그림"을 만들어야한다면, (페인트에 직접 접근 할 수 없기 때문에) 어떻게 할 것인가? –

+0

스윙 구성 요소는 메서드를 사용하여 구성 요소의 상태를 변경합니다. 예를 들어, JLabel을 사용할 때 setText (...) 또는 setIcon (...)을 사용하여 상태를 변경할 수 있습니다. 그런 다음 구성 요소가 자체적으로 repaint()를 호출합니다. 따라서 귀하의 구성 요소에 다음 그림을 수행하도록 알리는 메소드가 필요합니다. – camickr