시소당
-파일구성-
PrintSample.java -메인클래스
PrintMonitor.java -프린팅작업관리
PrintComponent.java -프린트영역
PrintPreviewer.java -미리보기
TablePirnter.java -테이블데이터처리
SampleTableModel.java -데이터테이블
PrintSample.java
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
import javax.swing.*;
public class PrintSample extends JFrame{ //메인 실행 클래스
protected JTable table;
protected PageFormat pageFormat;
public static void main(String[] args){
PrintSample ps = new PrintSample();
ps.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ps.pack();
ps.setVisible(true);
}
public PrintSample(){ //생성자 함수
super("Sample Print Application");
table = new JTable(new SampleTableModel());
//샘플 테이블 인스턴스생성하여 인수로 넘겨준다
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); //테이블 리사이즈모드 오프
setContentPane(new JScrollPane(table)); //작업영역 스크롤페인에 테이블 삽입하여 설정
pageFormat = new PageFormat(); //페이지포멧 인스턴스 생성
buildMenuBar(); //메뉴생성 메소드 호출
}
protected void buildMenuBar(){ //메뉴생성 메소드
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.add(new AbstractAction("Page Setup", new ImageIcon("empty.gif")) {
public void actionPerformed(ActionEvent event){
onPageSetup(); //페이지 셋팅메소드 호출
}
});
menu.add(new AbstractAction("Print Preview", new ImageIcon("preview.gif")) {
public void actionPerformed(ActionEvent event){
onPrintPreview(); // 미리보기 메소드 호출
}
});
menu.add(new AbstractAction("Print", new ImageIcon("print.gif")) {
public void actionPerformed(ActionEvent event){
onPrint(); //프린트작업 실행메소드 호출
}
});
menu.addSeparator();
menu.add(new AbstractAction("Exit", new ImageIcon("empty.gif")) {
public void actionPerformed(ActionEvent event){
System.exit(0); //나가기
}
});
menuBar.add(menu);
setJMenuBar(menuBar); //현재 프레임에 메뉴바 세팅
}
protected void onPageSetup(){ //페이지세팅 메소드
Thread t = new Thread(new Runnable() {
public void run(){
PrinterJob pj = PrinterJob.getPrinterJob();
//현재시스템의 프린터인스턴스 가져와서 프린터잡 인스턴스 생성
pageFormat = pj.pageDialog(pageFormat); //다이얼로그 호출하여 페이지포멧 저장
}
});
t.start();
}
protected void onPrintPreview() { //미리보기 메소드
Thread t = new Thread(new Runnable(){
public void run(){
TablePrinter tp = new TablePrinter(table, pageFormat);
//샘플테이블과 페이지를 인스턴스로 넘겨주어 테이블 프린터 객체 생성
PrintPreviewer pp = new PrintPreviewer(tp, 0);
//테이블 프린터객체를 인수로 넘겨주어 미리보기객체 생성
JDialog dlg = new JDialog(PrintSample.this, "Print Preview");
//다이얼로그 출력, 오너는 현재창...
dlg.getContentPane().add(pp);
//다이얼로그 작업영역 가져온후 미리보기 패널 추가(작업영역 미리보기패널로 설정)
dlg.setSize(400, 300);
dlg.setVisible(true);
}
});
t.start();
}
protected void onPrint(){ //실제 출력메소드
Thread t = new Thread(new Runnable(){
public void run(){
TablePrinter tp = new TablePrinter(table, pageFormat); //테이블프린터 객체 생성
PrintMonitor pm = new PrintMonitor(tp);
//테이블프린터 객체를 인수로 넘겨주어 프린터모니터 객체 생성
try{
pm.performPrint(true); //프린트 실행...
}catch(PrinterException pe){
JOptionPane.showMessageDialog(PrintSample.this, "Printing error:"+pe.getMessage());
//에러발생시 메시지박스 출력
}
}
});
t.start();
}
}
PrintMonitor.java
import java.awt.print.*;
import javax.swing.*;
public class PrintMonitor implements Pageable{ //프린팅 작업관리 클래스
protected PrinterJob printerJob;
protected Pageable pageable;
protected JOptionPane optionPane;
protected JDialog statusDialog;
public PrintMonitor(Pageable p){
pageable = p;
printerJob = PrinterJob.getPrinterJob();
String[] Options = {"Cancel"};
optionPane = new JOptionPane("", JOptionPane.INFORMATION_MESSAGE, JOptionPane.CANCEL_OPTION, null, Options);
statusDialog = optionPane.createDialog(null, "Printer Job Status");
}
public void performPrint(boolean showDialog) throws PrinterException {
printerJob.setPageable(this);
if(showDialog){
boolean isOk = printerJob.printDialog();
if(!isOk) return;
}
optionPane.setMessage("Initiating printer job...");
Thread t = new Thread(new Runnable(){
public void run(){
statusDialog.setVisible(true);
if(optionPane.getValue() !=
JOptionPane.UNINITIALIZED_VALUE){
printerJob.cancel();
}
}
});
t.start();
printerJob.print();
statusDialog.setVisible(false);
}
public int getNumberOfPages(){
return pageable.getNumberOfPages();
}
public Printable getPrintable(int index){
optionPane.setMessage("Printing page " + (index + 1));
return pageable.getPrintable(index);
}
public PageFormat getPageFormat(int index){
return pageable.getPageFormat(index);
}
}
PrintComponent.java
import java.awt.*;
import java.awt.geom.*;
import java.awt.print.*;
import javax.swing.*;
import javax.swing.border.*;
public class PrintComponent extends JPanel{//프린트될부분을 컴포넌트에 표시
protected Printable printable; //Printable 인스턴스변수 선언
protected PageFormat pageFormat; //PageFormat 인스턴스변수 선언
protected int displayPage; //표시할 페이지번호를 저장
protected double scaleFactor; //스케일을 저장할 변수 선언
public PrintComponent(Printable p, PageFormat pf){
//생성자 함수, Printable과 PageFormat 개체를 인수로 넘겨받아,
setPrintable(p);//선언했던 Printable변수와
setPageFormat(pf);//PageFormat변수에 저장
setDisplayPage(0);//표시할 페이지인덱스는 0(첫번째),
setScaleFactor(100);//스케일은 100%
setBackground(Color.white);//배경색은 흰색으로 세팅
}
public void setPrintable(Printable p){ //Printable 세팅
printable = p;
revalidate();//
}
public void setPageFormat(PageFormat pf){ //PageFormat 세팅
pageFormat = pf;
revalidate();//갱신
}
public void setDisplayPage(int page){ //displayPage세팅
displayPage = page;
revalidate();//갱신
}
public void setScaleFactor(double scale){//스케일 세팅
scaleFactor = scale;
revalidate();//갱신
}
public double getScaleFactor(){//현재 스케일 리턴
return scaleFactor;
}
public Dimension getSizeWithScale(double scale){
Insets insets = getInsets();
int width = ((int)(pageFormat.getWidth() * scale / 100d))+
insets.left + insets.right;
int height = ((int)(pageFormat.getHeight() * scale / 100d)) + insets.top + insets.bottom;
return new Dimension(width, height);
}
public Dimension getPreferredSize(){
return getSizeWithScale(scaleFactor);
}
public Dimension getMinimumSize(){
return getPreferredSize();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle clipRect = g2.getClipBounds();
AffineTransform at = g2.getTransform();
int x = (int)(pageFormat.getImageableX() * scaleFactor / 100d);
int y = (int)(pageFormat.getImageableY() * scaleFactor / 100d);
int w = (int)(pageFormat.getImageableWidth() * scaleFactor / 100d);
int h = (int)(pageFormat.getImageableHeight() * scaleFactor / 100d);
g2.clipRect(x, y, w, h);
g2.scale(scaleFactor / 100, scaleFactor / 100);
try{
printable.print(g, pageFormat, displayPage);
}catch(PrinterException pe){};
g2.setTransform(at);
g2.setClip(clipRect);
}
}
PrintPreviewer.java
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
import javax.swing.*;
import javax.swing.border.*;
public class PrintPreviewer extends JPanel{ //프린트 미리보기 클래스, 각종 기능들을 구현..
protected Pageable pageable;
protected PrintComponent printComponent;
protected int pageIndex;
protected JScrollPane scrollPane;
protected JButton previousButton;
protected JButton nextButton;
protected JButton sizeButton;
protected JTextField scaleText;
public PrintPreviewer(Pageable p, int page){
pageable = p;
pageIndex = page;
printComponent = new PrintComponent(null, null);
printComponent.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
buildLayout();
displayPage(pageIndex);
}
protected void buildLayout(){
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
panel.add(printComponent);
scrollPane = new JScrollPane(panel);
add(scrollPane, BorderLayout.CENTER);
add(getButtomPanel(), BorderLayout.SOUTH);
addListener();
}
protected JPanel getButtomPanel(){
JPanel outer= new JPanel();
outer.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 0));
JPanel inner = new JPanel();
inner.setLayout(new GridLayout(1, 2, 10, 0));
previousButton = new JButton("Previous");
inner.add(previousButton);
nextButton = new JButton("Next");
inner.add(nextButton);
outer.add(inner);
scaleText = new JTextField(3);
outer.add(scaleText);
sizeButton = new JButton("Size to Fit");
outer.add(sizeButton);
return outer;
}
protected void addListener(){
previousButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
displayPage(pageIndex -1);
}
});
nextButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
displayPage(pageIndex + 1);
}
});
sizeButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
sizeToFit();
}
});
scaleText.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
try{
int scale = Integer.parseInt(scaleText.getText());
printComponent.setScaleFactor(scale);
}catch(NumberFormatException nfe){};
}
});
}
protected void displayPage(int index){
pageIndex = index;
printComponent.setPrintable(pageable.getPrintable(pageIndex));
printComponent.setPageFormat(pageable.getPageFormat(pageIndex));
printComponent.setDisplayPage(index);
previousButton.setEnabled(pageIndex > 0);
nextButton.setEnabled(pageIndex < (pageable.getNumberOfPages() - 1));
repaint();
}
protected void sizeToFit(){
int newScaleFactor;
Dimension compSize = printComponent.getSizeWithScale(100d);
Dimension viewSize = scrollPane.getSize();
int scaleX = (viewSize.width - 25) * 100 / compSize.width;
int scaleY = (viewSize.height - 25) * 100 / compSize.height;
newScaleFactor = Math.min(scaleX, scaleY);
printComponent.setScaleFactor(newScaleFactor);
scaleText.setText(Integer.toString(newScaleFactor));
repaint();
}
}
SampleTableModel.java
import javax.swing.table.*;
public class SampleTableModel extends AbstractTableModel{ //출력할 테이블 구현 클래스
public final static String[] columnNames = {"Name", "Address", "Phone", "Postal Code", "Date"};
public final static Object[][] values = {
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"},
{"Janet Abel", "1117 Sampson Street", "3184397830", "70669-0531", "2009/10/3"},
{"Debbie Anderson", "3420 Davis Road", "3184941888", "70669-0645", "1999/7/15"},
{"Teri White", "2516 WestWood Road", "4194040262", "80669-8884", "2005/6/12"}};
public int getRowCount(){
return values.length;
}
public int getColumnCount(){
return 5;
}
public Object getValueAt(int row, int column){
return values[row][column];
}
public String getColumnName(int column){
return columnNames[column];
}
}
TablePrinter.java
import java.awt.*;
import java.awt.print.*;
import javax.swing.*;
import javax.swing.table.*;
//실제데이터를 처리하는 클래스, 이미 만들어진 테이블 대신 데이터를 인수로 넘겨 표시...
//데이터(테이블)을 프린트할 수 있는 상태로 변환하여 저장하고있다.
public class TablePrinter implements Printable, Pageable{
//실제 출력할 데이터 처리 클래스, Printable인터페이스와 Pageable인터페이스 구현
protected JTable table; //테이블 처리할 인스턴스 변수 선언
protected PageFormat pageFormat; //페이지포멧 인스턴스변수 선언
protected int headerStatus = ALL_PAGES;
public final static int ALL_PAGES = 0;
public final static int FIRST_PAGE_ONLY = 1;
public final static int NO_PAGES = 2;
public TablePrinter(JTable tbl, PageFormat pf){
//생성자, 테이블개체와 페이지포멧 개체를 인수로 받아 각각의 변수에 저장
table = tbl;
pageFormat = pf;
}
public int print(Graphics g, PageFormat pf, int index){
//Printable인터페이스의 추상메소드 구현
Dimension size = null;
if((table.getWidth() == 0) || (table.getHeight() == 0)){ //테이블의 넓이나 높이가 0이면,
table.setSize(table.getPreferredSize()); //컴포넌트에 의한 사이즈값으로 세팅
}
int tableWidth = table.getWidth(); //테이블 너비 가져와 변수에 세팅
int tableHeight = table.getHeight(); //테이블 높이 가져와 변수에 세팅
int positionX = 0; //X위치로 사용할 변수 0으로 세팅
int positionY = 0;//Y위치로 사용할 변수 0으로 세팅
int pageIndex = 0; //페이지 번호로 사용할 변수 0으로 세팅
while (positionY < tableHeight){ //반복문... positionY변수값이 테이블 높이보다 작다면..
positionX = 0; //positionX변수 0으로 세팅
while(positionX < tableWidth){
size = getPrintSize(positionX, positionY);
//getPinrtSize메소드에 positionX, positionY변수 인수로 전달하여 리턴된 size 값 저장
if(pageIndex == index){
//루프를 돌며 인수로 온 index값이 PageIndex와 같은지 비교하고 같다면,
paintTable(g, positionX, positionY, size);//테이블을 표시한고,
return Printable.PAGE_EXISTS;
//PAGE_EXISTS 상수를 리턴하여 Printable에 랜더링된 페이지가 있음을 알린다.
}
pageIndex++; //pageIndex를 1증가 시킴
positionX += size.width; //positionX에 size 너비값을 더해 저장.
}
positionY += size.height; //positionY에 size 높이값을 더해 저장.
}
return Printable.NO_SUCH_PAGE;
//NO_SUCH_PAGE 상수 리턴하여 Printable에 랜더링된 페이지가 더이상 없음을 알린다.
}
protected Dimension getPrintSize(int positionX, int positionY){ //프린트가능한 사이즈를 리턴
Rectangle rect;
int printWidth; //프린트가능한 너비를 저장할 변수
int printHeight; //프린트가능한 높이를 저장할 변수
int firstCol = table.columnAtPoint(new Point(positionX, positionY));
//입력된 좌표에 대해 테이블 컬럼의 인덱스를 리턴
int firstRow = table.rowAtPoint(new Point(positionX, positionY));
//입력된 좌표에 대해 테이블열의 인텍스를 리턴
int maxWidth = (int)(pageFormat.getImageableWidth());
//페이지포멧으로부터 이미지출력 가능한 너비를 가져와 maxWidth변수에 저장
int maxHeight = (int)(pageFormat.getImageableHeight());
// 페이지포멧으로부터 이미지출력 가능한 높이를 가져와 maxHeight변수에 저장
if(displayHeaderOnPage(positionY)){
// positionY변수를 인자로 넘겨받아 테이블헤더 표시여부를 결정.
maxHeight -= table.getTableHeader().getHeight();
//조건에 맞다면 최대높이에서 테이블헤더 만큼의 높이를 뺀다.
}
int lastCol = table.columnAtPoint(new Point(positionX + maxWidth, positionY));//최대 너비에 대한 좌표에 대해 마지막 컬럼의 인덱스를 구해 리턴
if(lastCol == -1){ //만약 해당 좌표에 컬럼이 없다면,
printWidth = table.getWidth() - positionX;
//테이블 너비에서 positionX만큼 제한ㅤㄱㅓㅄ을 printWidth에 저장
}
else{ //컬럼이 존재한다면,
rect = table.getCellRect(0, lastCol - 1, true); //마지막컬럼의 위 컬럼의 크기를 저장
printWidth = rect.x + rect.width - positionX;
//위의 마지막 컬럼의 상자크기값에서 x좌표값과 너비를 더하고 positionX값을 뺀 값을 변수에저장
}
int lastRow = table.rowAtPoint(new Point(positionX, positionY + maxHeight));
//위와 동일한 작업
if(lastRow == -1){
printHeight = table.getHeight() - positionY;
}
else {
rect = table.getCellRect(lastRow - 1, 0, true);
printHeight = rect.y + rect.height - positionY;
}
return new Dimension(printWidth, printHeight); //프린트 작업영역 리턴..
}
protected void paintTable(Graphics g, int positionX, int positionY, Dimension size){//테이블을 그려내기위한 메소드
int offsetX = (int)(pageFormat.getImageableX());//페이지포멧에서 이미지X좌표 얻어오기
int offsetY = (int)(pageFormat.getImageableY());//페이지포멧에서 이미지Y좌표 얻어오기
if(displayHeaderOnPage(positionY)){ //헤더 표시유무 확인, True면
JTableHeader header = table.getTableHeader();//table에서 테이블헤더를 가져와 변수에 저장,
if((header.getWidth() == 0) || (header.getHeight() == 0)) {//만약 헤더너비나 높이가 0이라면,
header.setSize(header.getPreferredSize());//기본적인 size값을 세팅
}
int headerHeight = header.getHeight();//헤더에서 높이가져와 변수에 저장
g.translate(offsetX - positionX, offsetY);//인수로 얻은 값 만큼 펜 이동
g.clipRect(positionX, 0, size.width, size.height + headerHeight);
//지정 좌표를 클립(처음 clipRect가 호출되었으므로 새로운클립이됨)한 후,
header.paint(g);//헤더 그리기..
g.translate(0, headerHeight - positionY);//원점으로 되돌리기..
g.clipRect(positionX, positionY, size.width, size.height);//지정좌표를 클립
}else{
g.translate(offsetX - positionX, offsetY - positionY);//좌표이동
g.clipRect(positionX, positionY, size.width, size.height);//클립
}
table.paint(g);// 테이블 그리기...
}
protected boolean displayHeaderOnPage(int positionY){ //헤더 표시여부를 검사
return((headerStatus == ALL_PAGES) || ((headerStatus == FIRST_PAGE_ONLY) && positionY == 0));
}//headerStatus가 ALL_PAGES(0) 이거나 headerStatus가 FIRST_PAGE_ONLY(1) 이고 positionY값이 0이면 true, 아니면 false리턴.
public int getNumberOfPages(){
//Pageable 인터페이스의 추상메소드 구현, 페이지 번호를 리턴하는 메소드
Dimension size = null;
int tableWidth = table.getWidth(); //테이블의 너비와 높이를 저장
int tableHeight = table.getHeight();
int positionX = 0;
int positionY = 0;
int pageIndex = 0;
while(positionY < tableHeight){//테이블높이가 positionY보다 크면,
positionX = 0; //positionX를 0으로 초기화
while(positionX < tableWidth){ //테이블너비가 positionX보다 크면,
size = getPrintSize(positionX, positionY);
//getPrintSize메소드에 인수를 넘겨주어 인쇄가능 사이즈를 얻어온다.
positionX += size.width;//positionX에 size의 너비값을 더해주고,
pageIndex ++;//페이지 인덱스를 1증가, while문 조건으로 이동
}
positionY += size.height;//positionY에 size의 높이값을 더한다.
}//while문 조건으로 이동
return pageIndex;
}
public Printable getPrintable(int index){
//Pageable 인터페이스의 추상메소드 구현, 해당 페이지 번호의 Printable 리턴
return this;
}
public PageFormat getPageFormat(int index){
//Pageable 인터페이스의 추상메소드 구현, 해당 페이지번호의 페이지 포멧을 리턴
return pageFormat;
}
}