DOC-04-09 打印HTML内容
本章教会你如何打印WebView组件中加载的Web页面。
使用JavaFX8中提供的打印API,你可以打印JavaFX程序的图形化内容。在javafx.print包中有对应的类和枚举。
9.1 使用打印API
要想在JavaFX程序中启用打印功能,你需要使用PrinterJob类。该类表示与系统默认打印机相关联的一个打印任务。使用Printer类来控制一个打印机来执行特定的打印任务。对于每一个打印任务,你都可以通过使用JobSetting类的属性来指定任务设置,如校对(collation)、份数(copies)、页面布局(pageLayout)、页面范围(pageRanges)、纸张来源(paperSource)、打印颜色(printColor)、打印分辨率(printResolution)、打印质量(printQuality)和单双面(printSides)。
你可以打印场景图的任何节点,包括根节点。你也可以打印那些没添加到场景中的节点。使用printPage方法job.printPage(node)来为某node初始化一个打印任务。有关打印功能的更多信息请参考JavaFX8的API说明。
在使用JavaFX的web组件时,你通常需要打印一个加载到浏览器中的HTML页面而不是程序UI本身。这就是为什么WebEngine类中添加了print方法,此方法就是为了打印与webEngine对象关联的HTML页面而生的。
9.2 添加上下文菜单启用打印功能
通常来讲,你需要把打印指令添加到程序的菜单或者工具栏中。在WebViewSample程序中,工具栏放了太多控件了,所以需要把打印功能放到点击鼠标右键弹出的菜单中。例9-1展示了如何把拥有打印功能的弹出式菜单放到程序工具栏中的代码片段。
例9-1创建工具栏的弹出式菜单
Java
//adding context menu
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = new MenuItem("Print");
cm.getItems().add(cmItem1);
toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
if (e.getButton() == MouseButton.SECONDARY) {
cm.show(toolBar, e.getScreenX(), e.getScreenY());
}
});
1
2
3
4
5
6
7
8
9
//adding context menu
finalContextMenucm=newContextMenu();
MenuItemcmItem1=newMenuItem("Print");
cm.getItems().add(cmItem1);
toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED,(MouseEvente)->{
if(e.getButton()==MouseButton.SECONDARY){
cm.show(toolBar,e.getScreenX(),e.getScreenY());
}
});
把上例中的代码片段加到之前的WebViewSample程序中,运行以后右键点击工具栏打印菜单即出现了,如图9-1所示。
图9-1拥有打印功能的弹出式菜单
9.3 处理打印任务
将打印的菜单添加到程序UI中以后,就可以定义打印的动作了。首先,你需要创建一个PrinterJob对象;然后,调用WebEngine.print方法,将该printJob对象作为参数传进去。请参考例9-2。
例9-2调用WebEngine.print方法
Java
//processing print job
cmItem1.setOnAction((ActionEvent e) -> {
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
webEngine.print(job);
job.endJob();
}
});
1
2
3
4
5
6
7
8
//processing print job
cmItem1.setOnAction((ActionEvente)->{
PrinterJobjob=PrinterJob.createPrinterJob();
if(job!=null){
webEngine.print(job);
job.endJob();
}
});
对printerJob的非空判断很重要,因为如果系统中没有可用的打印机则createPrinterJob方法会返回null。
学习例9-3中添加了打印功能的WebViewSample的完整代码。
例9-3启用了打印功能的WebViewSample
Java
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener.Change;
import javafx.concurrent.Worker.State;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.PopupFeatures;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebHistory.Entry;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class WebViewSample extends Application {
private Scene scene;
@Override
public void start(Stage stage) {
// create scene
stage.setTitle("Web View Sample");
scene = new Scene(new Browser(stage), 900, 600, Color.web("#666970"));
stage.setScene(scene);
// apply CSS style
scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
// show stage
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class Browser extends Region {
private final HBox toolBar;
final private static String[] imageFiles = new String[]{
"product.png",
"blog.png",
"documentation.png",
"partners.png",
"help.png"
};
final private static String[] captions = new String[]{
"Products",
"Blogs",
"Documentation",
"Partners",
"Help"
};
final private static String[] urls = new String[]{
"http://www.oracle.com/products/index.html",
"http://blogs.oracle.com/",
"http://docs.oracle.com/javase/index.html",
"http://www.oracle.com/partners/index.html",
WebViewSample.class.getResource("help.html").toExternalForm()
};
final ImageView selectedImage = new ImageView();
final Hyperlink[] hpls = new Hyperlink[captions.length];
final Image[] images = new Image[imageFiles.length];
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
final Button toggleHelpTopics = new Button("Toggle Help Topics");
final WebView smallView = new WebView();
final ComboBox comboBox = new ComboBox();
private boolean needDocumentationButton = false;
public Browser(final Stage stage) {
//apply the styles
getStyleClass().add("browser");
for (int i = 0; i < captions.length; i++) {
// create hyperlinks
Hyperlink hpl = hpls[i] = new Hyperlink(captions[i]);
Image image = images[i]
= new Image(getClass().getResourceAsStream(imageFiles[i]));
hpl.setGraphic(new ImageView(image));
final String url = urls[i];
final boolean addButton = (hpl.getText().equals("Help"));
// process event
hpl.setOnAction((ActionEvent e) -> {
needDocumentationButton = addButton;
webEngine.load(url);
});
}
comboBox.setPrefWidth(60);
// create the toolbar
toolBar = new HBox();
toolBar.setAlignment(Pos.CENTER);
toolBar.getStyleClass().add("browser-toolbar");
toolBar.getChildren().add(comboBox);
toolBar.getChildren().addAll(hpls);
toolBar.getChildren().add(createSpacer());
//set action for the button
toggleHelpTopics.setOnAction((ActionEvent t) -> {
webEngine.executeScript("toggle_visibility('help_topics')");
});
smallView.setPrefSize(120, 80);
//handle popup windows
webEngine.setCreatePopupHandler(
(PopupFeatures config) -> {
smallView.setFontScale(0.8);
if (!toolBar.getChildren().contains(smallView)) {
toolBar.getChildren().add(smallView);
}
return smallView.getEngine();
});
//process history
final WebHistory history = webEngine.getHistory();
history.getEntries().addListener(
(Change extends Entry> c) -> {
c.next();
c.getRemoved().stream().forEach((e) -> {
comboBox.getItems().remove(e.getUrl());
});
c.getAddedSubList().stream().forEach((e) -> {
comboBox.getItems().add(e.getUrl());
});
});
//set the behavior for the history combobox
comboBox.setOnAction((Event ev) -> {
int offset
= comboBox.getSelectionModel().getSelectedIndex()
- history.getCurrentIndex();
history.go(offset);
});
// process page loading
webEngine.getLoadWorker().stateProperty().addListener(
(ObservableValue extends State> ov, State oldState,
State newState) -> {
toolBar.getChildren().remove(toggleHelpTopics);
if (newState == State.SUCCEEDED) {
JSObject win
= (JSObject) webEngine.executeScript("window");
win.setMember("app", new JavaApp());
if (needDocumentationButton) {
toolBar.getChildren().add(toggleHelpTopics);
}
}
});
//adding context menu
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = new MenuItem("Print");
cm.getItems().add(cmItem1);
toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
if (e.getButton() == MouseButton.SECONDARY) {
cm.show(toolBar, e.getScreenX(), e.getScreenY());
}
});
//processing print job
cmItem1.setOnAction((ActionEvent e) -> {
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
webEngine.print(job);
job.endJob();
}
});
// load the home page
webEngine.load("http://www.oracle.com/products/index.html");
//add components
getChildren().add(toolBar);
getChildren().add(browser);
}
// JavaScript interface object
public class JavaApp {
public void exit() {
Platform.exit();
}
}
private Node createSpacer() {
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
@Override
protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
double tbHeight = toolBar.prefHeight(w);
layoutInArea(browser,0,0,w,h-tbHeight,0,HPos.CENTER,VPos.CENTER);
layoutInArea(toolBar,0,h-tbHeight,w,tbHeight,0,HPos.CENTER,VPos.CENTER);
}
@Override
protected double computePrefWidth(double height) {
return 900;
}
@Override
protected double computePrefHeight(double width) {
return 600;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
importjavafx.application.Application;
importjavafx.application.Platform;
importjavafx.beans.value.ObservableValue;
importjavafx.collections.ListChangeListener.Change;
importjavafx.concurrent.Worker.State;
importjavafx.event.ActionEvent;
importjavafx.event.Event;
importjavafx.geometry.HPos;
importjavafx.geometry.Pos;
importjavafx.geometry.VPos;
importjavafx.print.PrinterJob;
importjavafx.scene.Node;
importjavafx.scene.Scene;
importjavafx.scene.control.Button;
importjavafx.scene.control.ComboBox;
importjavafx.scene.control.ContextMenu;
importjavafx.scene.control.Hyperlink;
importjavafx.scene.control.MenuItem;
importjavafx.scene.image.Image;
importjavafx.scene.image.ImageView;
importjavafx.scene.input.MouseButton;
importjavafx.scene.input.MouseEvent;
importjavafx.scene.layout.HBox;
importjavafx.scene.layout.Priority;
importjavafx.scene.layout.Region;
importjavafx.scene.paint.Color;
importjavafx.scene.web.PopupFeatures;
importjavafx.scene.web.WebEngine;
importjavafx.scene.web.WebHistory;
importjavafx.scene.web.WebHistory.Entry;
importjavafx.scene.web.WebView;
importjavafx.stage.Stage;
importnetscape.javascript.JSObject;
publicclassWebViewSampleextendsApplication{
privateScenescene;
@Override
publicvoidstart(Stagestage){
// create scene
stage.setTitle("Web View Sample");
scene=newScene(newBrowser(stage),900,600,Color.web("#666970"));
stage.setScene(scene);
// apply CSS style
scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
// show stage
stage.show();
}
publicstaticvoidmain(String[]args){
launch(args);
}
}
classBrowserextendsRegion{
privatefinalHBoxtoolBar;
finalprivatestaticString[]imageFiles=newString[]{
"product.png",
"blog.png",
"documentation.png",
"partners.png",
"help.png"
};
finalprivatestaticString[]captions=newString[]{
"Products",
"Blogs",
"Documentation",
"Partners",
"Help"
};
finalprivatestaticString[]urls=newString[]{
"http://www.oracle.com/products/index.html",
"http://blogs.oracle.com/",
"http://docs.oracle.com/javase/index.html",
"http://www.oracle.com/partners/index.html",
WebViewSample.class.getResource("help.html").toExternalForm()
};
finalImageViewselectedImage=newImageView();
finalHyperlink[]hpls=newHyperlink[captions.length];
finalImage[]images=newImage[imageFiles.length];
finalWebViewbrowser=newWebView();
finalWebEnginewebEngine=browser.getEngine();
finalButtontoggleHelpTopics=newButton("Toggle Help Topics");
finalWebViewsmallView=newWebView();
finalComboBoxcomboBox=newComboBox();
privatebooleanneedDocumentationButton=false;
publicBrowser(finalStagestage){
//apply the styles
getStyleClass().add("browser");
for(inti=0;i
// create hyperlinks
Hyperlinkhpl=hpls[i]=newHyperlink(captions[i]);
Imageimage=images[i]
=newImage(getClass().getResourceAsStream(imageFiles[i]));
hpl.setGraphic(newImageView(image));
finalStringurl=urls[i];
finalbooleanaddButton=(hpl.getText().equals("Help"));
// process event
hpl.setOnAction((ActionEvente)->{
needDocumentationButton=addButton;
webEngine.load(url);
});
}
comboBox.setPrefWidth(60);
// create the toolbar
toolBar=newHBox();
toolBar.setAlignment(Pos.CENTER);
toolBar.getStyleClass().add("browser-toolbar");
toolBar.getChildren().add(comboBox);
toolBar.getChildren().addAll(hpls);
toolBar.getChildren().add(createSpacer());
//set action for the button
toggleHelpTopics.setOnAction((ActionEventt)->{
webEngine.executeScript("toggle_visibility('help_topics')");
});
smallView.setPrefSize(120,80);
//handle popup windows
webEngine.setCreatePopupHandler(
(PopupFeaturesconfig)->{
smallView.setFontScale(0.8);
if(!toolBar.getChildren().contains(smallView)){
toolBar.getChildren().add(smallView);
}
returnsmallView.getEngine();
});
//process history
finalWebHistoryhistory=webEngine.getHistory();
history.getEntries().addListener(
(Change<?extendsEntry>c)->{
c.next();
c.getRemoved().stream().forEach((e)->{
comboBox.getItems().remove(e.getUrl());
});
c.getAddedSubList().stream().forEach((e)->{
comboBox.getItems().add(e.getUrl());
});
});
//set the behavior for the history combobox
comboBox.setOnAction((Eventev)->{
intoffset
=comboBox.getSelectionModel().getSelectedIndex()
-history.getCurrentIndex();
history.go(offset);
});
// process page loading
webEngine.getLoadWorker().stateProperty().addListener(
(ObservableValue<?extendsState>ov,StateoldState,
StatenewState)->{
toolBar.getChildren().remove(toggleHelpTopics);
if(newState==State.SUCCEEDED){
JSObjectwin
=(JSObject)webEngine.executeScript("window");
win.setMember("app",newJavaApp());
if(needDocumentationButton){
toolBar.getChildren().add(toggleHelpTopics);
}
}
});
//adding context menu
finalContextMenucm=newContextMenu();
MenuItemcmItem1=newMenuItem("Print");
cm.getItems().add(cmItem1);
toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED,(MouseEvente)->{
if(e.getButton()==MouseButton.SECONDARY){
cm.show(toolBar,e.getScreenX(),e.getScreenY());
}
});
//processing print job
cmItem1.setOnAction((ActionEvente)->{
PrinterJobjob=PrinterJob.createPrinterJob();
if(job!=null){
webEngine.print(job);
job.endJob();
}
});
// load the home page
webEngine.load("http://www.oracle.com/products/index.html");
//add components
getChildren().add(toolBar);
getChildren().add(browser);
}
// JavaScript interface object
publicclassJavaApp{
publicvoidexit(){
Platform.exit();
}
}
privateNodecreateSpacer(){
Regionspacer=newRegion();
HBox.setHgrow(spacer,Priority.ALWAYS);
returnspacer;
}
@Override
protectedvoidlayoutChildren(){
doublew=getWidth();
doubleh=getHeight();
doubletbHeight=toolBar.prefHeight(w);
layoutInArea(browser,0,0,w,h-tbHeight,0,HPos.CENTER,VPos.CENTER);
layoutInArea(toolBar,0,h-tbHeight,w,tbHeight,0,HPos.CENTER,VPos.CENTER);
}
@Override
protecteddoublecomputePrefWidth(doubleheight){
return900;
}
@Override
protecteddoublecomputePrefHeight(doublewidth){
return600;
}
}
若想扩充WebViewSample程序的打印功能,请使用javafx.print包中的类。
在你的JavaFX程序中,你可以使用TabPane类实现浏览器标签页功能,当用户添加新的标签页时创建新的WebView对象即可。
若要进一步增强该程序,你可以应用特效、变形和动画转换。你也可以添加更多的WebView实例到程序的scene中。
参考JavaFX的API文档和JavaFX CSS规范了解更多可用特性的信息。你也可以学习JavaFX in Swing tutorial来学习如何在你已有的Swing程序中添加WebView组件。
相关API文档
● WebView
● WebEngine
● WebHistory
● Region
● Hyperlink
● Worker
打赏一下
支付宝
微信