2011년 6월 9일 목요일

JDK 1.4의 프린팅 (printing), Part 1

새로운 Java Print Service API
John Zukowski
사장, JZ Ventures, Inc.
2002년 3월
1.1 이후 모든 새로운 자바 플랫폼 출시판은 플랫폼의 인쇄 지원 프레임워크에 변화를 가져왔던 것처럼 보인다. Merlin도 예외는 아니다. 이번 달의 Magic with Merlin 에서 John Zukowski는 최신 인쇄 기능에 관한 2회에 걸친 논의를 시작한다.
여러분이 일정 기간 동안 자바 플랫폼으로 작업해 왔다면 여러분은 아마 나처럼 인쇄 API가 끝없이 계속 변경되는데 혼란을 겪었을 것이다. Merlin도 자바 플랫폼에 또 다른 세트의 인쇄 기능과 기법들을 가져왔다. Java Print Service API라고 이름 붙여진 이 최신 기법은 1999년부터 Java Community Process에서 작업되어 왔다. 다행히도 이 새 API는 긍정적인 추가라 할 수 있고 당분간 인쇄 지원에 있어 마지막 중요 변화가 될 것이다.
새로운 Print Services API로 인쇄하려면 발견, 지정, 인쇄라는 세 부분으로 된 프로세스가 필요하다. 선택적인 네 번째 부분은 인쇄 작업이 진행될 때 통지하는 것이다. 이 글에서 우리가 작업할 모든 클래스와 인터페이스는 javax.print 패키지나 이 패키지의 하위 패키지 중 하나에 들어 있다. (참고 자료)
프린터 찾기
인쇄 작업을 수행하기 위한 첫번째 단계는 인쇄할 프린터나 프린터 세트를 확인하는 것이다. 프린터 객체는 프린트 서비스 (print services)라고 불리며, 확인 절차는 검색 (lookup)이라고 불린다. 검색 작업을 위한 지원 클래스는 PrintServiceLookup라고 적절하게 불린다. 프린트 서비스를 검색하려면 Listing 1에 나와 있는 세 가지 메소드 중 하나를 사용한다.
Listing 1. 프린트 서비스 검색하기
 public static final PrintService
   lookupDefaultPrintService()
 public static final PrintService[]
   lookupPrintServices(DocFlavor flavor, AttributeSet attributes)
 public static final MultiDocPrintService[]
   lookupMultiDocPrintServices(DocFlavor[] flavors,
       AttributeSet attributes)


세 메소드는 각각 다른 작업에 사용된다.:
  • lookupDefaultPrintService()은 기본 프린트 서비스를 반환한다.
  • lookupPrintServices()은 특정 속성을 가지고 (양면 인쇄등) 특정 문서 유형 (GIF등)의 인쇄를 지원하는 프린터 세트를 반환한다.
  • lookupMultiDocPrintServices()은 한 번에 여러 문서를 인쇄하는 것을 지원한다..

여러분이 사용할 프린트 서비스를 찾은 후에는 인쇄 job을 생성해야 한다. 나중에 이 job에 출력을 보낼 것이다. 검색 결과 반환된 PrintService는 자신의 createPrintJob() 메소드로 job을 생성하는데 사용될 수 있는데, 이는 다음과 같다.:
 PrintService printService =
   PrintServiceLookup.lookupDefaultPrintService();
 DocPrintJob job = printService.createPrintJob();


출력 포맷 지정하기
어디에 인쇄할지 지정해야 할 뿐 아니라 인쇄 문서의 포맷도 지정해야 한다. DocFlavor 클래스 (혹은 이 클래스의 하위 클래스)가 쓸모 있는 곳이 바로 여기이다. DocFlavor 클래스는 여러분이 인쇄할 객체의 MIME (Multipurpose Internet Mail Extensions) 유형을 확인하는데 사용된다. MIME 유형은 전자식 데이터가 어떻게 해석되어야 하는지를 설명한다. 여러분은 전자 우편이나 첨부문서 작업을 할 때 MIME 유형을 만났을 것이다. 하지만 MIME 사양은 데이터 형식을 확인하기 위한 보다 일반적인 목적의 메커니즘을 기술하고 있다.
Merlin은 포맷을 정의하기 위해 7개의 DocFlavor 하위 클래스를 자신의 내부 클래스로 제공한다. 이 클래스들은 세 개의 MIME 하위 유형으로 나누어진다.: 바이트 지향형, 문자 지향형 및 서비스 지향형이 그것이다. 바이트 지향형 옵션들은 다음과 같다. :
  • BYTE_ARRAY
  • INPUT_STREAM
  • URL

문자 지향형 옵션은 다음과 같다.:
  • CHAR_ARRAY
  • READER
  • STRING

서비스 지향형 내부 클래스는 SERVICE_FORMATTED이다.
내부 클래스 내의 내부 클래스
각 옵션 유형은 자체적인 MIME 유형 세트를 지원한다. 이 MIME 유형들이 다시 한번 내부 클래스로 정의된다. 다음과 같이 19개의 바이트 지향형 옵션이 있다. :
  • AUTOSENSE
  • GIF
  • JPEG
  • PCL
  • PDF
  • PNG
  • POSTSCRIPT
  • TEXT_HTML_HOST
  • TEXT_HTML_US_ASCII
  • TEXT_HTML_UTF_16
  • TEXT_HTML_UTF_16BE
  • TEXT_HTML_UTF_16LE
  • TEXT_HTML_UTF_8
  • TEXT_PLAIN_HOST
  • TEXT_PLAIN_US_ASCII
  • TEXT_PLAIN_UTF_16
  • TEXT_PLAIN_UTF_16BE
  • TEXT_PLAIN_UTF_16LE
  • TEXT_PLAIN_UTF_8

문자 지향형 스트림은 보다 평범하여, 다음 두 포맷만을 제공한다.:
  • TEXT_HTML
  • TEXT_PLAIN

서비스 중심 스트림은 세 개의 포멧을 포함한다. :
  • PAGEABLE
  • PRINTABLE
  • RENDERABLE_IMAGE

여러분은 옵션을 다음과 같이 구성한다. (이 예에서는 PNG 이미지로) :
DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG;


인쇄 속성 지정하기
인쇄할 때 여러분은 문서를 어떻게 인쇄하기 원하는지를 기술하는 속성을 지정할 수 있다. 속성의 예로는 인쇄 매수, 인쇄할 페이지 및 문서 이미지 유형 (예 : 가로 대 세로)등이 있다. 속성을 지정하려면 다음 두 클래스 중 하나를 사용해야 한다.:
  • DocAttributeSet 한 문서의 특성을 지정한다.
  • PrintRequestAttributeSet 한 인쇄 작업의 특성을 지정한다.

인쇄를 수행하기 위해 속성을 지정하려면 먼저 적절한 세트의 인스턴스를 생성하고 (DocAttributeSet or PrintRequestAttributeSet), 그 다음 여러분의 인쇄를 수행하기 위해 원하는 속성을 그 인스턴스에 채운다. 여러분이 지정하지 않은 속성들은 적절한 기본값으로 구성될 것이다. javax.print.attribute 패키지는 약 70개의 서로 다른 속성을 가지고 있는데, 각각은 별개의 클래스로 정의된다. 각 속성은 한 개, 혹은 그 이상의 속성 세트와 함께 작동된다. 이 글에서 설명한 두 속성 세트 외에 정보 조회를 위해 또 다른 두 개의 세트를 이용할 수도 있다. javax.print.attribute 패키지에서 모든 유형들을 찾아볼 수 있다.
다음은 PrintRequestAttributeSet를 사용하고 그 객체를 5부 인쇄하는 프린트 실행이다.:
 PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
 pras.add(new Copies(5));


사용 가능한 모든 속성의 목록은 javax.print.attribute 패키지를 보아야 한다.
내용 설정하기
Doc 인터페이스는 인쇄 job에 데이터를 제공한다. 인터페이스의 구현자는 SimpleDoc 클래스이다. 단 하나의 생성자가 사용되며, 여러분은 인쇄 내용을 첫번째 매개변수로, 옵션을 두 번째 매개변수로, 속성을 세 번째 매개변수로 제공한다. 생성자는 다음과 같다.:
 public SimpleDoc(Object printData, DocFlavor flavor,
 DocAttributeSet attributes)


그러면 데이터 문제가 남는다. 그 답은 DocFlavor에 달려 있다. 여러분이 DocFlavor.INPUT_STREAM의 옵션을 지정하면 데이터는 그 InputStream에 의해 확인될 것이다. 여러분이 DocFlavor.BYTE_ARRAY를 지정했다면 데이터는 하나의 바이트 배열 (byte [ ])이 될 것이다.
따라서 PNG 이미지 파일을 인쇄하려면 Listing 2에 나와 있는 구문을 사용한다.
Listing 2. 내용 설정하기
DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG;
 String filename = ...;
 FileInputStream fis = new FileInputSteam(filename);
 DocAttributeSet das = new HashDocAttributeSet();
 Doc doc = new SimpleDoc(fis, flavor, das);


인쇄하기
일단 여러분이 프린터를 확인하고 출력 포맷, 속성 및 내용을 지정했다면 남겨진 일은 인쇄뿐이다. 실제 인쇄 job은 Listing 3과 같이 PrintService로부터 조회되는 DocPrintJob의 print() 메소드를 통해 실행된다.
Listing 3.인쇄 job
 DocPrintJob job = ...;
 PrintRequestAttributeSet pras = ...;
 Doc doc = ...;
 job.print(doc, pras);


print()를 호출하면 여러분은 인쇄 내용을 다른 스레드를 통하여 프린트 서비스로 보내는 메커니즘을 작동하게 된다.
인쇄 설정 화면
지금까지 주목할만한 것이 하나 빠졌는데 이것은 인쇄 설정 화면이다. 인쇄 설정 화면은 여러분이 그래픽 기반으로 프린터 속성을 구성하도록 해주는 시스템 팝업을 말한다.
흥미롭게도, 인쇄 설정 화면의 기본 행동이 새로운 API에서는 바뀌었다: 설정 화면은 기본적으로 나타나지 않는다. 따라서 여러분은 위와 같은 인쇄 설정 화면을 만들기 위해서 ServiceUI 클래스를 사용해야 한다.
ServiceUI 클래스는 프린터 선택 화면을 표시하도록 하는 하나의 메소드를 제공한다.:
printDialog(GraphicsConfiguration gc, int x, int y,
 PrintService[] services, PrintService defaultService,
 DocFlavor flavor, PrintRequestAttributeSet attributes)


그러면 여러분은 반환된 PrintService를 사용하여 인쇄할 DocPrintJob을 얻는데, Listing 4와 같다.
Listing 4. 인쇄 설정 화면으로 인쇄하기
 String filename = ...;
 PrintRequestAttributeSet pras = ...;
 DocFlavor flavor = ...;
 PrintService printService[] =
   PrintServiceLookup.lookupPrintServices(flavor, pras);
 PrintService defaultService =
   PrintServiceLookup.lookupDefaultPrintService();
 PrintService service = ServiceUI.printDialog(null, 200, 200,
   printService, defaultService, flavor, pras);
 if (service != null) {
   DocPrintJob job = service.createPrintJob();
   FileInputStream fis = new FileInputStream(filename);
   DocAttributeSet das = new HashDocAttributeSet();
   Doc doc = new SimpleDoc(fis, flavor, das);
   job.print(doc, pras);
 }


실행 예제
여러분이 새로운 Print Service API의 기능을 시도해 보도록 해 줄 실행 예제로 이 글을 마무리하겠다. 다음 코드는 앞의 모든 예제 코드들을 하나의 실행 가능한 프로그램으로 결합시킨 것이다. 프로그램을 실행시킬 때 반드시 PNG 이미지 파일의 이름을 명령행에 전해야 한다. 다른 포맷을 인쇄하고 싶을 경우 DocFlavor을 바꾸기만 하면 된다.
Listing 5. 인쇄 예제
import javax.print.*;
import javax.print.attribute.*;
import java.io.*;

public class Printing {
 public static void main(String args[]) throws Exception {
   String filename = args[0];
   PrintRequestAttributeSet pras =
     new HashPrintRequestAttributeSet();
   DocFlavor flavor = DocFlavor.INPUT_STREAM.PNG;
   PrintService printService[] =
     PrintServiceLookup.lookupPrintServices(flavor, pras);
   PrintService defaultService =
     PrintServiceLookup.lookupDefaultPrintService();
   PrintService service = ServiceUI.printDialog(null, 200, 200,
     printService, defaultService, flavor, pras);
   if (service != null) {
     DocPrintJob job = service.createPrintJob();
     FileInputStream fis = new FileInputStream(filename);
     DocAttributeSet das = new HashDocAttributeSet();
     Doc doc = new SimpleDoc(fis, flavor, das);
     job.print(doc, pras);
     Thread.sleep(10000);
   }
   System.exit(0);
 }
}


Magic with Merlin 연재의 다음 편에서 여러분은 화면이나 컴포넌트의 내용을 인쇄하는 방법에 관해 배울 것이다. 또한 인쇄와 관련된 이벤트 처리 작업도 설명할 것이고, 여러분의 인쇄 작업에서 sleep() 호출을 없애는 방법도 보여 주겠다.

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...