본문 바로가기
연구하기/Computer Engineering

Java AWT - 페인팅 이벤트의 처리

by 썰렁황제 2010. 1. 27.
  Java AWT 환경에서 처음에 가장 오해하기 쉬운 부분 중 하나가 바로 페인팅 프로세스이다. 과거 한참 AWT 파고 있던 본인도 마찬가지의 실수를 범한 것이기도 하다.

  Java 의 GUI 근간을 형성하는 Component 위에 원하는 형태를 그리려면 paint(Graphics) 메소드를 오버라이딩하여 원하는 것을 그려야 한다는 점은 익히 잘 알고 있으리라 생각한다. (update 메소드 및 Canvas 등에 대해서는 여기선 별도로 언급하지 않겠다) 그리고 이렇게 구현된 paint(Graphics) 메소드 및 컴포넌트의 기본적인 형태를 그리는 작업이 컴포넌트를 그려야만 하는 여러 가지 상황, 혹은 사용자의 요청에 의해서 수행된다는 것 역시도 기본적인 AWT 에 대한 지식이 있다면 잘 알고 있으리라 생각한다. 중요한 점은 이 페인팅 작업이 이벤트 큐잉을 통하여 처리되는 방식이라는 것이고, 이에 대해 제대로 이해하지 못하고 코딩을 수행할 경우 여러 가지 예상치 못한 결과를 가져오게 된다.

  흔히 컴포넌트를 다시 그리는 작업을 수행할 때 사용되는 repaint() 메소드가 이러한 문제를 발생시키는 좋은 예이다. repaint() 를 호출하면 즉시 컴포넌트를 다시 그릴 것이라고 간주하고 이후 처리하게 코딩하는 경우가 많은데 실제로는 그렇게 동작하지 않으므로 난감한 상황에 이르는 경우가 많다.

  이의 동작은 실제로는 아래와 같다.


  즉 repaint() 메소드를 호출하면, 즉시 페인팅 작업을 수행하는 것이 아니라, 페인트 이벤트 발생으로 취급, AWT 이벤트 큐에 페인트 이벤트를 집어넣고 종료시킨다. 그리고 이벤트 큐에 먼저 얹어져 있던 이벤트들이 차곡차곡 처리되고 난 다음 비로소 페인트 이벤트가 수행되고, 이에 따라 해당 컴포넌트의 paint(Graphics) 메소드가 호출되는 것이다.

  이런 이벤트 큐 형식으로 처리되기 때문에, repaint() 호출이 AWT 이벤트 처리기와 동일한 스레드, 즉 이벤트 핸들러로부터 동작되는 코드 흐름이었다면 해당 이벤트 핸들러로 시작된 코드 흐름이 완전히 종료되기 전까지는 절대 페인팅 이벤트가 처리되지 않을 것이므로, repaint() 호출 직후에 무슨 짓을 해도 paint(Graphics) 가 바로 호출되게 할 수는 없다. 이에 대해서는 아래의 그림을 참조하자


  repaint() 의 호출이 이벤트 핸들 코드 흐름이 아닌 다른 스레드라 할 지라도 위의 구조로 인해 repaint() 와 실제로 paint(Graphics) 간의 거리를 확정하기 어렵고, 많은 경우 둘간의 간극은 꽤 느린 편이므로 repaint() 호출 직후에 뭔가 코드를 써 넣는다고 하더라도 paint(Graphics) 호출 뒤에 실행될 가능성은 매우 낮다.

  따라서 이런 이벤트 처리 시퀀스와 독립적으로 페인팅 작업을 수행하려 한다면, 다른 메소드를 호출해야 한다. 이를 위해 제공되는 것이 바로 paintImmediately() 이다. 이 메소드는 호출하면 메소드 명칭 그대로 '즉시' 페인팅을 수행한다.
 
반응형