JavaFX PrintAPI错误的PaperSource
我正在使用JavaFx Print-Dialog来定制打印作业。 所有属性都将存储在PrinterJob#JobSettings变量中,但是当我从jobSetting接收纸张来源时,纸张来源始终是默认设置。
我如何获取我设置的纸张来源?
这是一个简短的例子:
public class PrinterPaperSourceTest extends Application {
public static void main(String[] args) {
launch( args );
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Printer");
Button btn = new Button();
btn.setText("Show Printer Settings ");
btn.setOnAction( new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
PrinterJob job = PrinterJob.createPrinterJob(Printer.getDefaultPrinter());
job.showPageSetupDialog(null);
Alert alert = new Alert(AlertType.INFORMATION);
PaperSource paperSource = job.getJobSettings().getPaperSource();
alert.setContentText("PaperSource: " + paperSource.getName());
alert.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
我没有答案,但我会试着解释为什么会发生,以及为什么它不容易修复。 这种行为似乎受到Internet打印协议(IPP)规范的影响,并且是由Java Print Service API(JavaFX打印作业委托给其执行)执行IPP的方式引起的。 以下是Oracle技术说明中的一个片段,它解释了手动设置纸张来源的限制(https://docs.oracle.com/javase/8/docs/technotes/guides/jps/spec/attributes.fm5.html):
介质是标识要在其上进行打印的介质的IPP属性。 媒体属性是理解的重要属性,但相对复杂。
Java Print Service API定义抽象类Media的三个子类,以反映IPP规范中的重载媒体属性:MediaSizeName,MediaName和MediaTray。 所有媒体子类都具有媒体类别,每个子类都为其定义不同的标准属性值。 [...]
媒体属性的值始终是一个字符串,但由于该属性被重载,其值将决定属性引用的媒体的类型。 例如,IPP预定义的一组属性值包括值“a4”和“top-tray”。 如果媒体设置为值“a4”,则媒体属性是指纸张的大小,但是如果媒体设置为“顶部纸盘”,则媒体属性是指纸张来源。 [...]
在大多数情况下,应用程序将使用MediaSizeName或MediaTray。 MediaSizeName类按大小枚举媒体。 MediaTray类枚举打印机上的纸盒,通常包括主纸盒和手动进纸盒。 IPP 1.1规范没有规定同时指定介质尺寸和介质托盘,这意味着例如应用程序无法从手动托盘请求尺寸为A4的纸张。 未来版本的IPP规范可能会提供一次请求多种类型的媒体的方法,在这种情况下,JPS API很可能会得到增强以实现此更改。
因此, MediaTray
(或纸张来源)不是一个独立参数,如果Media
属性已由其他两种方式之一( MediaSizeName
或MediaName
)定义,则无法设置该参数。 这正是页面设置对话框发生的情况。
J2DPrinterJob
类(来自com.sun.prism.j2d.print
包)包含对话框代码并更新打印作业设置(我通过调试应用程序发现了这一点)。 以下是此类中更新对话框中纸张来源设置的方法。
private void updatePaperSource() {
Media m = (Media)printReqAttrSet.get(Media.class);
if (m instanceof MediaTray) {
PaperSource s = j2dPrinter.getPaperSource((MediaTray)m);
if (s != null) {
settings.setPaperSource(s);
}
}
}
我测试了不同的场景,结果相同:在updatePaperSource()
开始执行时, Media
属性已被定义为MediaSizeName
类型。 所以if分支中的语句永远不会执行,这就是为什么纸源不会更新。
我怀疑纸张类型或纸张尺寸优先于纸张来源,并且因为页面设置对话框始终定义纸张类型(没有“自动”选项),所以纸张来源选择过载以避免属性冲突。 这基本上使这个选项无用。
这可能是JDK中的一个错误或有意的设计决策。 无论如何,考虑到它来自Java内部API中的私有方法,我看不出一个简单的方法来解决JavaFX中存在的这个问题。
打印API出现在fx8.0中。 它可以打印节点。 您可以使用javafx.print.PrinterJob
类创建打印机作业。 但它只打印适合打印页面的区域,而不打印在屏幕上。 所以你需要通过手动使节点适合页面(缩放,翻译等)。
您可以使用此代码。 希望它能帮助你。
/**
* Prints the current page displayed within the internal browser, not necessarily the {@link #presentationProperty()}.
* If no printers are installed on the system, an awareness is displayed.
*/
public final void print() {
final PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
if (job.showPrintDialog(null)) {
if(this.getPresentation().getArchive() != null) {
final String extension = ".".concat(this.getPresentation().getArchiveExtension());
final int indexOfExtension = this.getPresentation().getArchive().getName().indexOf(extension);
final String jobName = this.getPresentation().getArchive().getName().substring(0, indexOfExtension);
job.getJobSettings().setJobName(jobName);
}
job.getJobSettings().setPrintQuality(PrintQuality.HIGH);
job.getJobSettings().setPageLayout(job.getPrinter().createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, 0, 0, 0, 0));
this.internalBrowser.getEngine().print(job);
job.endJob();
} else {
job.cancelJob();
}
} else {
DialogHelper.showError("No printer", "There is no printer installed on your system.");
}
}
资源链接:
经过大量的搜索后,我找到了一种用javafx打印到另一个托盘的方法,这是我查看的第一个地方,所以我想这里是发布我的解决方案的最佳位置,它可能因不同的托盘名称而异我的托盘2它也会打印出所有可用的托盘
private void printImage(Node node) {
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
JobSettings js = job.getJobSettings();
PaperSource papersource = js.getPaperSource();
System.out.println("PaperSource=" + papersource);
PrinterAttributes pa = printer.getPrinterAttributes();
Set<PaperSource> s = pa.getSupportedPaperSources();
System.out.println("# of papersources=" + s.size());
if (s != null) {
for (PaperSource newPaperSource : s) {
System.out.println("newpapersource= " + newPaperSource);
//Here is where you would put the tray name that is appropriate
//in the contains section
if(newPaperSource.toString().contains("Tray 2"))
js.setPaperSource(newPaperSource);
}
}
job.getJobSettings().setJobName("Whatever You want");
ObjectProperty<PaperSource> sources = job.getJobSettings().paperSourceProperty();
System.out.println(sources.toString());
boolean success = job.printPage(node);
if (success) {
System.out.println("PRINTING FINISHED");
job.endJob();
//Stage mainStage = (Stage) root.getScene().getWindow();
//mainStage.close();
}
}
}
这是我的输出:
PaperSource=Paper source : Automatic
# of papersources=6
newpapersource= Paper source :
newpapersource= Paper source : Manual Feed in Tray 1
newpapersource= Paper source : Printer auto select
newpapersource= Paper source : Tray 1
newpapersource= Paper source : Tray 2
newpapersource= Paper source : Form-Source
ObjectProperty [bean: Collation = UNCOLLATED
Copies = 1
Sides = ONE_SIDED
JobName = Whatever
Page ranges = null
Print color = COLOR
Print quality = NORMAL
Print resolution = Feed res=600dpi. Cross Feed res=600dpi.
Paper source = Paper source : Tray 2
Page layout = Paper=Paper: Letter size=8.5x11.0 INCH Orient=PORTRAIT leftMargin=54.0 rightMargin=54.0 topMargin=54.0 bottomMargin=54.0, name: paperSource, value: Paper source : Tray 2]
PRINTING FINISHED
链接地址: http://www.djcxy.com/p/34775.html