JPanel an Drucker printen

JavaRentner

Aktives Mitglied
Hallo Wissende
Mit folgendem Code drucke ich an einen Physischen Drucker:
Java:
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.PrinterName;

public class DoPrint {

    private Component druckKomponente;
    int ausgabe = 0;
   
    private Printable prnt = new Printable() {
        @Override
        public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
            double gBreite, gHoehe;
            double skalierung = 0.0;

            if ( pageIndex > 0 ) {
                return( NO_SUCH_PAGE );
            } else {

                //Skalierung*******************************
                gBreite = pageFormat.getImageableWidth();
                gHoehe = pageFormat.getImageableHeight();
                skalierung = gBreite / gHoehe;
                //*****************************************
               
                Graphics2D g2d = (Graphics2D)g;
                g2d.translate( pageFormat.getImageableX(), pageFormat.getImageableY() );
                g2d.scale( skalierung, skalierung );
                druckKomponente.paint( g2d );
                return( PAGE_EXISTS );
            }
        }
    };

    /**
     * Drucken einer Komponente
     * @param c die Komponente (<i>JPanel, JTextField, usw.</i>)
     * @param printer Name des Printers (<i>z.B. Canon_MF720C_Series</i>)
     * @param tray Name des Tray aus dem das Papier geladen werden soll.
     * @param jobName Information f&uuml;r den Drucker.
     * @param l (<i>left</i>) linker Randabstand
     * @param t (<i>top</i>) oberer Randabstand
     * @param w (<i>width</i>) Breite
     * @param h (<i>height</i>) H&ouml;he
     */
    public void print(Component c, String printer, String tray, String jobName, double l, double t, double w, double h) {
        druckKomponente = c;

        PrinterJob printJob = PrinterJob.getPrinterJob();
        PrintService drucker = null;
        try {
            drucker = getPrinter(printer);
            printJob.setPrintService(getPrinter(printer));
        } catch (PrinterException e) {
            e.printStackTrace();
        }

        PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
        if(tray != null) {
            if(!tray.equals("")) {
                attr.add(getMediaTray(drucker, tray));
            }
        }

        PageFormat pageFormat = new PageFormat();
        pageFormat.setOrientation( PageFormat.PORTRAIT );   //Hoch- oder Querformat (Standard: hoch)
       
        double dpFaktor = 72.0;
        Paper a4PortraitPaper = new Paper();
        final double cm2inch = 0.03937;  // = 1 mm
        double paperHeight = 297 * cm2inch;
        double paperWidth = 210 * cm2inch;
        a4PortraitPaper.setSize((paperWidth * dpFaktor), (paperHeight * dpFaktor));
       
        a4PortraitPaper.setImageableArea(l, t, w, h);
       
        pageFormat.setPaper( a4PortraitPaper );

        printJob.getJobName().describeConstable();
        printJob.setJobName(jobName);
        printJob.setPrintable(prnt, pageFormat);
       
        try {
            printJob.print(attr);
        } catch (PrinterException e) {
            // STEP Automatisch generierter Erfassungsblock
            e.printStackTrace();
        }

        // Ruft den printDialog auf !!!!!!!!!! will ich aber nicht!
        /*
        if ( printJob.printDialog() ) {
            try {
                printJob.print();
            } catch( PrinterException pe ) {
                System.out.println( "Error printing: " + pe );
                System.out.println( "Error printing (Message): " + pe.getMessage() );
                System.out.println( "Error printing (Localized Message): " + pe.getLocalizedMessage() );
                System.out.println( "Error printing (Cause): " + pe.getCause() );
            }
        }
        */
    }

    private PrintService getPrinter(String printerName) {
        AttributeSet aset = new HashAttributeSet();
        aset.add(new PrinterName(printerName, null));
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null, aset);
        for (PrintService service : services) {
            if (service.getName().equals(printerName)) {
                return service;
            }
        }
        return null;
    }
    private MediaTray getMediaTray(PrintService printer, String trayName) {      
        DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
        Object o = printer.getSupportedAttributeValues(Media.class, flavor, null);
        if (o != null && o.getClass().isArray()) {
            for (Media media : (Media[]) o) {
                if (media instanceof MediaTray) {
                    if(media.toString().equals(trayName)) {
                        return (MediaTray) media;
                    }
                }
            }
        }
        return null;
    }

    public ArrayList<String> printerTrays(String printerName) {
        ArrayList<String> temp = new ArrayList<>();
        AttributeSet aset = new HashAttributeSet();
        aset.add(new PrinterName(printerName, null));
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null, aset);
        for (int i = 0; i < services.length; i++) {
            PrintService service = services[i];
            DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
            Object o = service.getSupportedAttributeValues(Media.class, flavor, null);

            if (o != null && o.getClass().isArray()) {
                for (Media media : (Media[]) o) {
                    if (media instanceof MediaTray) {
                        temp.add(media.toString());
                    }
                }
            }
            if(temp.size() <= 0) {
                temp.add("Auto");
            }
        }
        return temp;
    }
}

In Linux und Mac (UNIX-Systeme) wird die übergebene Komponente korrek ausgedruckt!
Wo liegt der Fehler, dass in WINDOWS der Ausdruck völlig falsch gedruckt wird?

Ich finde den Fehler nicht!
Wie gesagt: ich bin und werde es bleiben, ein Anfänger.
Obigen code habe ich in openJDK13 gefunden und dank Eurer Hilfe anpassen können.

Was / Wie muss ich da was ändern, dass es auch für Windows passt? (getestet auf win7 und win10)
Soweit reichen meine banalen Kenntnisse nicht.

Vielen Dank!

PS:
Obiger Code druckt sogar auf dem ausgewählten Tray! 😀
Nur die Darstellung des Druckes pass in Windows NICHT!
 
Was heißt "völlig falsch gedruckt"?
heisst, dass Position Y ca. 5cm vom oberen Rand liegt und Position X ca. 2cm vom linken Rand ist.
Zudem werden die Schriftgrössen ca. 3x so gross gedruckt und ich daher nur 2/3 von X/Y her gesehen auf das Papier bekomme.
-> es werden keine weiteren Seiten gedruckt, weil es ja nur eine Seite A4 sein soll.

zudem rennt er 4x in die Methode:
public int print(...)
Entwede liegt der Fehler in public int print(...) oder hier
public void print(Component c, String printer, String tray, String jobName, double l, double t, double w, double h)...

bei folgendem Code:
Java:
        double dpFaktor = 72.0;
        Paper a4PortraitPaper = new Paper();
        final double cm2inch = 0.03937;  // = 1 mm
        double paperHeight = 297 * cm2inch;
        double paperWidth = 210 * cm2inch;
        a4PortraitPaper.setSize((paperWidth * dpFaktor), (paperHeight * dpFaktor));

Wie gesagt ich habe meinen Code aus diversen, im Internet gefundenen Code-Snippets zusammen gebastelt.
Nicht, dass ich eine Ahnung habe was ich da zusammengefrickelt habe! Aber in Linux läuft es super.

Erst als ich es auf einem Windows-PC ausführte, kamen die Probleme.
Für mich als Anfänger nicht mehr nachvollziehbar, warum...
Vielen Dank.
 
double paperHeight = 297 * cm2inch; double paperWidth = 210 * cm2inch;
Wenn ich das nicht für Windows auch mache, meldet der Drucker einen Fehler (Kein Papier...) und ich muss zum Drucker gehen und ihm sagen es sei ein A4 Normal (85g / mm2). Wobei der Ausdruck trotzem nicht passt.

Denke der Fehler liegt irgendwo bei weiteren Paremetern die übergeben werden müssen und Linux das automatisch macht.
Wie kann ich in Java dem Drucker einen Parameter mitgeben der mir sowas wie 1:1 (100%) druckt?

Java:
PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
In attr scheint es noch einige Möglichkeiten zu haben von denen ich mal nix verstehe... 🙁
Vielen Dank.
 
Habe mir mal erlaubt die zwei gescannten Ausdrucke anzuhängen.
-> Linux-Print.png ist absolut korrekt.
-> Win-Print.png wurde mit dem gleichen JAR gedruckt auf Windows-PC

Ich bin kein Java-Profi und kapiers wirklich nicht.
Gibt es denn niemand der mir weiterhelfen könnte?
 

Anhänge

  • Linux-Print.png
    Linux-Print.png
    1 MB · Aufrufe: 0
  • Win-Print.png
    Win-Print.png
    1,2 MB · Aufrufe: 0
Zuletzt bearbeitet:
Kann es sein, dass Graphics bereits skaliert wurde? Schau Dir mal an, was g2d.getTransform() liefert, bevor Du scale aufrufst.
 
Sorry dass ich mich erst jetzt wieder melde...
Kann es sein, dass Graphics bereits skaliert wurde? Schau Dir mal an, was g2d.getTransform() liefert, bevor Du scale aufrufst.
Ich glaube nicht...
Code:
System.out.println(g2d.getTransform());
liefert (da rennt er 4x durch):
AffineTransform[[4.166666666666667, 0.0, -0.0], [0.0, 4.166666666666667, -0.0]]
AffineTransform[[4.166666666666667, 0.0, -0.0], [0.0, 4.166666666666667, -0.0]]
AffineTransform[[4.166666507720948, 0.0, -50.171696183338824], [0.0, 4.166666507720948, -2664.1437416036315]]
AffineTransform[[4.166666507720948, 0.0, -64.8101771000329], [0.0, 4.166666507720948, -43.8556575153921]]
Ausgeführt im Code vom Post: #1
 
Habe jetzt herausgefunden, dass
in Windows attr.add(MediaSizeName.ISO_A4)
von attr.add(getMediaTray(drucker, tray)); überschrieben wird.
d.H. in Windows habe ich nur entweder: MediaSizeName.ISO_A4
oder getMediaTray(drucker, tray)!

Mit folgendem Code konnte ich das Problem lösen:
Java:
HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet() {
    private static final long serialVersionUID = 1L;
    HashMap<Class<?>, Attribute> map = new HashMap<>();
    @Override
    public Attribute[] toArray() {
        Attribute[] s = new Attribute[map.size()];
        map.values().toArray(s);
        return s;
    }
    @Override
    public int size() {
        return map.size();
    }
    @Override
    public boolean remove(Attribute attribute) {
        for (Entry<Class<?>, Attribute> e : map.entrySet()) {
            if (e.getValue() == attribute) {
                map.remove(e.getKey());
                return true;
            }
        }
        return false;
    }
    @Override
    public boolean remove(Class<?> category) {
        map.remove(category);
        return true;
    }
    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }
    @Override
    public Attribute get(Class<?> category) {
        return map.get(category);
    }
    @Override
    public boolean containsValue(Attribute attribute) {
        return map.containsValue(attribute);
    }
    @Override
    public boolean containsKey(Class<?> category) {
        return map.containsKey(category);
    }
    @Override
    public void clear() {
        map.clear();
    }
    @Override
    public boolean addAll(AttributeSet attributes) {
        return false;
    }
    @Override
    public boolean add(Attribute attribute) {
        if (attribute.getClass().toString().toLowerCase().contains("custom")) {
            map.put(Media.class, attribute);
        } else {
            map.put(attribute.getClass(), attribute);
        }
        return true;
    }
};
dann...
Java:
set.add(MediaSizeName.ISO_A4);
set.add(getMediaTray(drucker, tray));
jetzt habe ich auch in Windows beide Attribute.

Dieser Thread kann auf GELÖSST gesetzt werden.
 
Zuletzt bearbeitet:

Zurück
Oben