
【JDK8】迎接 JavaFX 8(2)
接著上一篇 JavaFX 2與8的比較,本篇將繼續介紹兩者間的差別。 列印功能 使用JavaFX 2開發應用程式,會發現JavaFX 2並沒有提供列印功能,因此欲列印內容,需自訂實作Java AWT的java.awt.print.Printable介面之類別,並實作Printable介面的print()方法,方可處理列印功能。 首先介紹如何實作Java AWT的Printable介面。 當執行列印時,首先以PrinterJob類別的getPrinterJob()方法建立PrinterJob物件,接著以setPrintable()方法顯示列印對話盒,其中setPrintable()方法之參數painter為Printable介面型別,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; ... } ... } 程式中以PageFormat的getImageableX()與getImageableY()方法取得版面可列印範圍的左上角座標,並利用java.awt.Graphics2D的translate()方法將所要列印的位置移到列印頁面的左上角: 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新增Printer與PrinterJob類別,類似於Java AWT的PrinterJob類別,但不似Java AWT般複雜。 當執行列印時,首先以Printer類別的getDefaultPrinter()方法取得作業系統預設的印表機,接著以createPageLayout()方法設定版面配置,如紙張大小 (A4、NA_LETTER)、列印方向 (LANDSCAPE、PORTRAIT)、上下左右邊界等,例如: 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(); } } DatePicker JavaFX 8新增DatePicker類別,用以選擇日期,使用上相當簡單,當點選DatePicker時,將觸發動作事件 (Action Event),藉由getValue()方法則可取得所選擇的日期,例如: final DatePicker datepicker = new DatePicker(); datepicker.setOnAction(event -> { // 取得所選擇的日期 LocalDate date = datepicker.getValue(); System.out.println("選擇的日期為: " + date); }); 【執行結果】 以下為未點選DatePicker時的樣式: 以下為點選DatePicker時的樣式: 3D JavaFX 8新增3D功能,與之前JavaFX 2的模擬3D不大一樣,例如新增Shape3D抽象類別,繼承自Shape3D抽象類別的3D物體包括Box, Cylinder, MeshView, Sphere等類別。 Shape3D抽象類別定義以下屬性:
以下是以Box類別分別以Wireframe、填色與貼圖等方式呈現立方體: 以下是以Cylinder類別分別以Wireframe、填色與貼圖等方式呈現圓柱體,此外Cylinder類別可設定divisions參數,設定圓柱體的分割等分,請參考第四張圖以divisions參數將圓柱體設定為八角柱體 (Octagonal Prism): 以下是以Sphere類別分別以Wireframe、填色與貼圖等方式呈現球體,與Cylinder類別相同,同樣可設定divisions參數,設定球體的分割等分,請參考第四張圖以divisions參數設定球體的分割等分: TriangleMesh TriangleMesh類別以頂點座標 (Vertex Coordinates)、三角形所形成的面 (Facet) 與貼圖 (Texture) 三者組成3D物體,為目前大部份3D軟體所使用的方法。 以立方體 (Cube) 為例,共有八個頂點與六個面,但就TriangleMesh而言,各個面是由兩個三角形所組成,因此共需設定八個頂點與十二個三角形,此外以「右手定則」定義各面的上下方向。下圖為立方體以Wireframe方式呈現的結果,可藉此瞭解如何以三角形組成面: 下圖是以填滿方式 (DrawMode.FILL) 呈現的結果: 再加上貼圖 (Texture): 瞭解TriangleMesh如何建立3D物體的概念之後,理論上只要知道頂點與如何形成各三角形的面,則可建立3D物體,但最困難的地方也就是頂點的取得。以下為一些特殊幾何物體的示範:
相關範例請參考: http://sites.google.com/site/leohkkimo/demo/javafx-3d PhongMaterial JavaFX使用Phong Shading著色法,又稱為Phong Interpolation或Normal-Vector Interpolation Shading,是由美國越南裔學者Bùi Tường Phong所發明,1973年發表於博士論文"Illumination of Computer-Generated Images", Department of Computer Science, University of Utah, UTEC-CSs-73-129, July 1973,因此以其姓氏Phong (裴)命名。 Phong Reflection Model是由Ambient Light (環境光)、Diffuse Light (漫射光) 與Specular Light (鏡面光) 三者所組成。 JavaFX以PhongMaterial類別處理Phong Material,並細分為Bump Map, Diffuse Map, Self Illumination Map, Specular Map, Diffuse Color, Specular Color, 與Specular Power,前四者Map用以設定貼圖、接著Color用以設定著色、最後Power用以設定強度,並定義以下屬性:
以下為分別設定Bump Map、Difffuse Map與Specular Map貼圖的效果: 以下為分別設定Difffuse Color與Specular Color的效果: 我們將在後續的內容中說明JavaFX 8的3D、TriangleMesh與PhongMaterial功能。 【參考資料】 [1] 黃嘉輝,深入研究JavaFX 2。 |