2014年6月4日 星期三

JavaFX 8 Print

使用JavaFX 2開發應用程式,會發現JavaFX 2並沒有提供列印功能,因此欲列印內容,需自訂實作Java AWT的java.awt.print.Printable介面之類別,並實作Printable介面的print()方法,方可處理列印功能。 首先介紹如何實作Java AWT的Printable介面。

當執行列印時,首先以PrinterJob類別的getPrinterJob()方法建立PrinterJob物件,接著以setPrintable()方法顯示列印對話盒,其中setPrintable()方法之參數painterPrintable介面型別,setPrintable()方法並不負責實際的列印動作,實際動作是由傳入之painter物件執行,painter物件需實作Printable介面,例如以下為自訂實作Printable介面之DocToPrinter類別,其中Printable介面的print()方法需被定義:
public class DocToPrinter implements java.awt.print.Printable {
  ... 
  public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
    Graphics2D g2d = (Graphics2D) g; 
    ... 
  } 
  ... 
}
程式中以PageFormatgetImageableX()getImageableY()方法取得版面可列印範圍的左上角座標,並利用java.awt.Graphics2Dtranslate()方法將所要列印的位置移到列印頁面的左上角:
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
g2d.setClip(
  (int)(pageFormat.getImageableX()/scale), 
  (int)(pageFormat.getImageableY()/scale), 
  (int)(pageFormat.getImageableWidth()/scale), 
  (int)(pageFormat.getImageableHeight()/scale)); 
... 
g2d.translate(g2d.getClipBounds().getX(), g2d.getClipBounds().getY()); 
【執行結果】

下圖為列印的執行結果,將開啟列印對話盒:
至於版面設定,首先以PrinterJob類別的getPrinterJob()方法建立PrinterJob物件,待建立之後則以pageDialog()方法顯示版面設定對話盒:
try { 
  PrinterJob prnJob = PrinterJob.getPrinterJob(); 
  // 顯示版面設定對話盒以設定邊界、列印方向、紙張大小、紙張來源、印表機等 
  pf = prnJob.pageDialog(prnJob.defaultPage()) ; 
} 
catch (Exception ex) {...} 
【執行結果】

下圖為版面設定之執行結果,此為作業系統之版面設定對話盒: 
但由於上述實作Printable介面的方式稍為複雜,因此Java SE 6.0新增列印功能,僅需以Java Swing的JTextComponent抽象類別之print()方法處理,相當簡單,例如:
try { 
  // 列印內容 
  jtextarea.print(); 
} 
catch (PrinterException ex) {...} 
【執行結果】

此方法將顯示Java樣式的列印對話盒,如下圖所示,有別於上述的列印對話盒,此外列印的格式亦不同,請比較兩者間之差異: 
有了上述的瞭解之後,接著說明JavaFX 8新增的列印功能。

JavaFX 8新增PrinterPrinterJob類別,類似於Java AWT的PrinterJob類別,但不似Java AWT般複雜。當執行列印時,首先以Printer類別的getDefaultPrinter()方法取得作業系統預設的印表機,接著以createPageLayout()方法設定版面配置,如紙張大小 (A4NA_LETTER)、列印方向 (LANDSCAPEPORTRAIT)、上下左右邊界等,例如:
Printer printer = Printer.getDefaultPrinter(); 
// 分別設定A4紙張、直垂列印方向、預設邊界 
PageLayout pageLayout = printer.createPageLayout( 
  Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.DEFAULT);
接著以PrinterJob類別的createPrinterJob()方法建立PrinterJob物件,以作為列印序列 (Queue) 之用,並以PrinterJob類別的printPage()方法列印,當列印完成時,則以PrinterJob類別的endJob()方法結束列印序列,例如:
PrinterJob job = PrinterJob.createPrinterJob(); 

if (job != null) { 
  boolean success = job.printPage(node); 

  if (success) { 
    job.endJob(); 
  } 
} 
【參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,
深入研究Java Swing。
[3] Java Official Web Site:http://www.oracle.com/technetwork/java/index.html
[4] JavaFX:http://www.oracle.com/technetwork/java/javafx
[5] JavaFX 8.0 API Specification.
[6] Java Platform, Standard Edition 8 API Specification.

© Chia-Hui Huang

3 則留言:

  1. 請教一下,之後書範例的問題已經下載解決了,感謝…

    Java有辦法直接列印,不要開對話框嗎?是要用Java2D去處理嗎?JDK7

    回覆刪除
  2. 哈…我自問自答,// OK = pj.printDialog();,這行不要就可以了…

    回覆刪除
    回覆
    1. Dear Linuxice0609

      謝謝你的詢問,問題解決就好

      另外我之前有用Java Swing寫了一個列印程式,若有需要請e-mail告訴我,我再寄給你

      我的e-mail: leohkkimo@gmail.com

      謝謝你

      Leo

      刪除