JavaFX PrintAPI错误的PaperSource

时间:2016-06-13 13:33:17

标签: java javafx printing

我使用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();
    }
}

3 个答案:

答案 0 :(得分:2)

打印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.");
    }
}

资源链接:

  1. javafx.print.PrinterJob examples
  2. Introduction by Example: JavaFX 8 Printing

答案 1 :(得分:1)

我没有答案,但我会尝试解释它为什么会发生以及为什么它不容易修复。此行为似乎受到Internet打印协议(IPP)规范的影响,并且是由Java Print Service API(JavaFX打印作业委托给它)实现IPP的方式引起的。以下是Oracle技术说明中的一个片段,解释了手动设置纸张来源的限制(https://docs.oracle.com/javase/8/docs/technotes/guides/jps/spec/attributes.fm5.html):

  

Media是IPP属性,用于标识要打印的介质。 Media属性是一个需要理解的重要属性,但相对复杂。

     

Java Print Service API定义了抽象类Media的三个子类,以反映IPP规范中的重载Media属性:MediaSizeName,MediaName和MediaTray。所有Media子类都具有Media类别,每个子类定义不同的标准属性值。 [...]

     

Media属性的值始终为String,但由于该属性已重载,因此其值确定属性所引用的媒体类型。例如,IPP预定义的一组属性值包括值&#34; a4&#34;和#34; top-tray&#34;。如果将媒体设置为值&#34; a4&#34;然后Media属性指的是纸张的大小,但是如果Media设置为&#34; top-tray&#34;然后Media属性指的是纸张来源。 [...]

     

在大多数情况下,应用程序将使用MediaSizeName或MediaTray。 MediaSizeName类按大小枚举媒体。 MediaTray类枚举打印机上的纸盘,打印机通常包括主托盘和手动进纸盘。 IPP 1.1规范不同时指定介质尺寸和介质托盘,这意味着,例如,应用程序无法从手动托盘请求A4纸张。未来IPP规范的修订可能提供了一种方法,一次请求多种类型的媒体,在这种情况下,JPS API很可能会得到增强,以实现此更改。

因此,MediaTray(或纸质来源)不是一个独立的参数,如果已经通过其他两种方式(Media或{之一定义了MediaSizeName属性,则无法设置{1}})。这正是页面设置对话框中发生的情况。

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类型。所以if分支中的语句永远不会被执行,这也就是纸质来源没有更新的原因。

我怀疑纸张类型或纸张尺寸优先于纸张来源,并且因为页面设置对话框始终定义纸张类型(没有“自动”选项),它会使纸张来源的选择超载以避免属性冲突。这实际上使这个选项无用。

这可能是JDK中的错误或有意的设计决策。无论如何,考虑到它来自Java内部API中的私有方法,我没有看到解决JavaFX中这个问题的简单方法。

答案 2 :(得分:0)

经过大量的搜索,我找到了一种方法用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