JavaFX PrintAPI mauvaise source de papier


J'utilise la boîte de dialogue d'impression JavaFX pour personnaliser le travail d'impression. Toutes les propriétés seront stockées dans la variable PrinterJob#JobSettings, mais lorsque je reçois la source papier du jobSetting, la source papier est toujours la valeur par défaut.

Comment puis-je obtenir la source papier que j'ai définie?

Voici un court exemple:

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();
    }
}
Author: ManoDestra, 2016-06-13

3 answers

Je n'ai pas de réponse mais je vais essayer d'expliquer pourquoi cela se produit et pourquoi ce ne sera pas facile à réparer. Ce comportement semble être influencé par les spécifications du protocole Internet Printing Protocol (IPP) et est dû à la manière dont IPP est implémenté par l'API Java Print Service (à laquelle les travaux d'impression JavaFX déléguent). Vous trouverez ci-dessous un fragment de la note technique d'Oracle qui explique les limites de la définition manuelle de la source papier (https://docs.oracle.com/javase/8/docs/technotes/guides/jps/spec/attributes.fm5.html):

Media est l'attribut IPP qui identifie le support sur lequel imprimer. L'attribut Media est un attribut important à comprendre, mais il est relativement complexe.

L'API Java Print Service définit trois sous-classes de la classe abstraite Media pour refléter l'attribut de média surchargé dans la spécification IPP: MediaSizeName, MediaName et MediaTray. Toutes les sous-classes de médias ont la catégorie de médias, pour laquelle chaque sous-classe définit différentes valeurs d'attribut standard. […]

La valeur de l'attribut Media est toujours une chaîne, mais comme l'attribut est surchargé, sa valeur détermine le type de média auquel l'attribut se réfère. Par exemple, l'IPP ensemble prédéfini de valeurs d'attribut inclure les valeurs "a4" et "haut plateau". Si Media est défini sur la valeur "a4", l'attribut Media fait référence à taille du papier, mais si Media est défini sur" top-tray", l'attribut Media fait référence à la source du papier. […]

Dans la plupart des cas, les applications utiliseront MediaSizeName ou MediaTray. La classe MediaSizeName énumère les médias par taille. La classe MediaTray énumère les bacs à papier d'une imprimante, qui comprennent généralement un bac principal et un bac d'alimentation manuel. La spécification IPP 1.1 ne prévoit pas de spécifier à la fois la taille du support et le plateau de support en même temps temps, ce qui signifie, par exemple, qu'une application ne peut pas demander du papier de format A4 à partir du bac manuel. Une révision future de la spécification IPP pourrait permettre de demander plus d'un type de support à la fois, auquel cas l'API JPS sera probablement améliorée pour mettre en œuvre ce changement.

Donc, MediaTray (ou paper source) n'est pas un paramètre indépendant et ne peut pas être défini si l'attribut Media est déjà défini par l'une des deux autres manières (MediaSizeName ou MediaName). C'est exactement ce qui se passe avec les boîtes de dialogue de configuration de page.

J2DPrinterJob la classe (du package com.sun.prism.j2d.print) contient le code de dialogue et met à jour les paramètres du travail d'impression (j'ai trouvé cela en déboguant votre application). Vous trouverez ci-dessous la méthode de cette classe qui met à jour le paramètre source papier à partir de la boîte de dialogue.

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);
        }
    }
}

J'ai testé différents scénarios et le résultat était le même: au moment où updatePaperSource() commence l'exécution, l'attribut Media est déjà défini comme type MediaSizeName. Donc les déclarations dans le si les branches ne sont jamais exécutées et c'est pourquoi la source papier n'est pas mise à jour.

Je soupçonne que le type de papier ou le format de papier ont la priorité sur la source de papier et parce que la boîte de dialogue de configuration de page définit toujours le type de papier (il n'y a pas d'option "automatique"), il surcharge la sélection de la source de papier pour éviter les conflits d'attributs. Cela rend essentiellement cette option inutile.

Il peut s'agir d'un bogue dans JDK ou d'une décision de conception intentionnelle. En tout cas, je ne vois pas de moyen facile de résoudre ce problème problème de rester dans JavaFX étant donné qu'il provient de méthodes privées dans l'API interne de Java.

 1
Author: Mosalx, 2016-06-26 13:44:28

L'API d'impression est apparue dans fx8.0. Et il peut imprimer les nœuds. Vous pouvez créer un travail d'imprimante avec la classe javafx.print.PrinterJob. Mais il imprime uniquement la région qui correspond à une page imprimée, et non celle que vous sur un écran. Vous devez donc faire votre page d'ajustement de nœud (échelle, traduction, etc.) à la main.

Vous pouvez utiliser ce code. Espérons qu'il saura vous aider.

/**
 * 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.");
    }
}

Lien de ressource:

  1. javafx.imprimer.PrinterJob exemples
  2. Introduction par exemple: JavaFX 8 Impression
 2
Author: SkyWalker, 2016-06-16 22:15:00

Après beaucoup de recherches, j'ai trouvé un moyen d'imprimer sur un plateau différent avec javafx et c'était le premier endroit où j'ai regardé, alors j'ai pensé que ce serait le meilleur endroit pour poster ma solution cela peut varier avec différents noms de plateau le mien était le plateau 2 il imprimera également tous les plateaux disponibles

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

Voici ma sortie:

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
 0
Author: Matt, 2017-09-06 21:13:02