Probleme mit drucken aus Java

JavaRentner

Aktives Mitglied
Guten Abend
mit folgendem Code wird mir ein JPanel grafisch korrekt ausgedruckt, wenn es MediaSizeName.ISO_A4; ist.
Habe ich irgendwo im Netz gefunden... (habe ein paar Zeilen eingefügt um zu verstehen was wo gerechnet wird)
Java:
private Printable prnt = new Printable() {

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            double gBreite, gHoehe;
            double faktorW = 0.0;
            double faktorH = 0.0;
            if ( pageIndex > 0 ) {    //if ( pageIndex > 0 ) {
                return(NO_SUCH_PAGE);
            } else {

                //Skalierung*******************************
                gBreite = pageFormat.getImageableWidth();
                gHoehe = pageFormat.getImageableHeight();
                faktorW = gBreite / druckKomponente.getWidth();
                faktorH = gHoehe / druckKomponente.getHeight();
               
                System.out.println("druckKomponente.getWidth()  = "+druckKomponente.getWidth());
                System.out.println("druckKomponente.getHeight() = "+druckKomponente.getHeight());
                System.out.println(".getImageableX() = "+pageFormat.getImageableX());
                System.out.println(".getImageableY() = "+pageFormat.getImageableY());
                System.out.println("------------------------------------------------------------------\n");
                //*****************************************

                Graphics2D g2d = (Graphics2D)graphics;
                g2d.translate( pageFormat.getImageableX(), pageFormat.getImageableY() );
                g2d.scale( faktorW, faktorH );
               
                disableDoubleBuffering( druckKomponente );
                druckKomponente.paint( g2d );
                enableDoubleBuffering( druckKomponente );
               
                return(PAGE_EXISTS);
            }
        }
    };
   
    ......

}
setzte ich aber MediaSizeName.ISO_C5;, dann ist die Position pageFormat.getImageableX() (Zeile 24) iwo bei -150 bis -200px
Ich verstehe die Logik nicht vom obigen Code... 🙁

MediaSizeName.ISO_C5; sind Couverts die im "Mehrzweck Papierfach" eingelegt sind (portrait, PageFormat.PORTRAIT; wurde gesetzt.)
Habs auch schon mit PageFormat.LANDSCAPE; versucht! Ohne Erfolg.

In der Höhe passt alles, nur Horizontal fängt er iwo bei -150 bis -200px an.

Wenn mir das mal Jemand erklären könnte, wäre super! 😄
Vielen Dank.

PS:
Meine SysOuts ergeben:
druckKomponente.getWidth() = 850
druckKomponente.getHeight() = 596
.getImageableX() = 6.947208000000103
.getImageableY() = 5.2501679999999995
 
Zuletzt bearbeitet:
pageFormat.getImageableWidth() -> Gibt die Breite des abbildbaren Bereichs der Seite in 1/72 eines Zolls zurück.
druckKomponente.getWidth() -> Gibt die aktuelle Breite der Komponente zurück. Das dürften aber Pixel sein.

Ich denke es macht keinen Sinn, für das Seitenverhältnis 2 unterschiedliche Einheiten in Relation zu setzen. Das dürfte dann immer ein Verhältnis kleiner als 1 zurückgeben. Bei der Skalierung wird dieser Wert mit der vorherigen Rendering-Operationen multipliziert. Das führt dann wieder zu sehr kleinen Werten. Daher denke ich, dass die Darstellung am Ende viel zu klein ist.
 
Vielen Dank.
Ich denke es macht keinen Sinn, für das Seitenverhältnis 2 unterschiedliche Einheiten in Relation zu setzen.
Habe ich jetzt korrigiert.

Das Problem ist aber, dass er mir für ein C5 Couvert >pageFormat.getImageableY() = 5.2501679999999995< auf der Basis eines A4 Dokuments ausrechnet:
Druckbeginn: (abbildbarer Bereich)
(1107 [A4-abbildbaren Bereich Höhe] /2)-(850 [C5-abbildbaren Bereich Breite] /2)-5.2501679999999995 [pageFormat.getImageableY()]


Was, wo muss ich im folgenden Code etwas ändern, dass pageFormat.getImageableY() = 5 auch auf einem C5 Couvert effektiv an der gewünschten Position pageFormat.getImageableY() liegt und nicht von der Mitte eines A4 nach oben gerechnet wird?:
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.HashMap;
import java.util.Map.Entry;
import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.PrinterName;
import javax.swing.RepaintManager;

public class DoPrint {

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

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

                    //Skalierung*******************************
                    gBreite = pageFormat.getImageableWidth();
                    gHoehe = pageFormat.getImageableHeight();
                    faktor = gBreite / druckKomponente.getWidth();

                    if(ausgabe == 0) { //sonst wird es 3x Ausgeworfen
                        ausgabe++;
                      
                        System.out.println("druckKomponente.getWidth()  = "+druckKomponente.getWidth()+"\tgBreite = "+gBreite);
                        System.out.println("druckKomponente.getHeight() = "+druckKomponente.getHeight()+"\tgHoehe = "+gHoehe);
                        System.out.println("faktorH = "+faktor);
                        System.out.println("pageFormat.getImageableX() = "+pageFormat.getImageableX());
                        System.out.println("pageFormat.getImageableY() = "+pageFormat.getImageableY());
                        System.out.println("------------------------------------------------------------------\n");
                    }
                    //*****************************************

                    Graphics2D g2d = (Graphics2D)graphics;
                    g2d.translate((pageFormat.getImageableX()), pageFormat.getImageableY() );
                  
//                    Habs für ISO_C5 auch mit folgender Zeile versucht -> OHNE ERFOLG
//                    g2d.translate((pageFormat.getImageableY()), (pageFormat.getImageableX()) );
                  
                    g2d.scale( faktor, faktor );
                  
                    disableDoubleBuffering( druckKomponente );
                    druckKomponente.paint( g2d );
                    enableDoubleBuffering( druckKomponente );
                  
                    return(PAGE_EXISTS);
                }
        }
    };

    /**
     * Drucken einer Komponente
     * @param c die Komponente (<i>JPanel, JTextField, usw.</i>) proportional zu <b>ISO_XX</b>
     * @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 isoTyp -> A4, C5, usw.
     * @param jobName Information f&uuml;r den Drucker.
     */
    public void print(Component c, String printer, String tray, String isoTyp, String jobName) {
      
        //aktClassDo 000-😈️ AUS- / EIN-Kommentieren
        //Wirft alle verfügbaren Attributs des gewählten Druckers (printer) aus.
//        System.out.println("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
//        PrintService[] MetaPrinter = PrintServiceLookup.lookupPrintServices(null, null);
//        for (PrintService service : MetaPrinter) {
//            if(service.getName().equals(printer)) {
//                Class<?>[] allAtributs = service.getSupportedAttributeCategories();
//                for(Class<?> c1: allAtributs) {
//                    System.out.println(c1.getTypeName());
//                }
//                break;
//            }
//        }
//        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");");
      
        druckKomponente = c;
        ausgabe = 0;
        System.out.println("Drucke ein "+isoTyp);

        //🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️ Attribute Methode-Interne KLASSE 🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭
        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;
            }
        };
        //🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️ FERTIG Attribute SETZEN 🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭️🇨🇭
      
        //aktClass 01-✔️ Media-Name/-Size SETZEN
        double mm2inch = 0.03937;  // = 1 mm
        double px2inch = 0.010417;
        double paperHeight = 0.0;
        double paperWidth = 0.0;
      
        double dpFaktor = 72.0;
      
        Paper paper = new Paper();
      
        double neux = (druckKomponente.getX()*px2inch)*dpFaktor;
        double neuy = (druckKomponente.getY()*px2inch)*dpFaktor;
        double neuw = (druckKomponente.getWidth()*px2inch)*dpFaktor;
        double neuh = (druckKomponente.getHeight()*px2inch)*dpFaktor;
        paper.setImageableArea(neux, neuy, neuw, neuh);
      
        PrinterJob printJob = PrinterJob.getPrinterJob();
        PrintService drucker = null;
        try {
            drucker = getPrinter(printer);
            printJob.setPrintService(getPrinter(printer));
        } catch (PrinterException e) {
            e.printStackTrace();
        }
      
        MediaSizeName msnISO = null;
      
        //Alle Print-Medien werden Hochformatig im Drucker eingelegt! (PageFormat.PORTRAIT)
        //d.H. sie werden alle an der schmalen Seite eingezogen.
        int orientation = PageFormat.PORTRAIT;
      
        switch (isoTyp) {
        case "A0":
            msnISO =  MediaSizeName.ISO_A0;
            break;
        case "A1":
            msnISO =  MediaSizeName.ISO_A1;
            break;
        case "A2":
            msnISO =  MediaSizeName.ISO_A2;
            break;
        case "A3":
            msnISO =  MediaSizeName.ISO_A3;
            break;
        case "A4":
            msnISO =  MediaSizeName.ISO_A4;
            paperWidth = 210 * mm2inch;
            paperHeight = 297 * mm2inch;
            break;
        case "A5":
            msnISO =  MediaSizeName.ISO_A5;
            break;
        case "C5":
            msnISO =  MediaSizeName.ISO_C5;
            paperWidth = (229 * mm2inch);
            paperHeight = (162 * mm2inch);
          
//            orientation = PageFormat.LANDSCAPE;
//            paperWidth = (162 * mm2inch);
//            paperHeight = (229 * mm2inch);
            break;
        case "A6":
            msnISO =  MediaSizeName.ISO_A6;
            break;
        case "A7":
            msnISO =  MediaSizeName.ISO_A7;
            break;
        }
        set.add(msnISO);
        paper.setSize((paperWidth * dpFaktor), (paperHeight * dpFaktor));
      
        //aktClass 02-✔️ tray für Druckr SETZEN
        if(tray != null && !tray.equals("")) {
            set.add(getMediaTray(drucker, tray));
        }
      
        PageFormat pageFormat = new PageFormat();
      
        //aktClass 03-✔️ Hoch/Quer-Format SETZEN
        pageFormat.setOrientation( orientation );   //Hoch- (1) oder Querformat (0) (Standard: hoch)
      
        //aktClass 04-✔️ Imageable-Area SETZEN
        pageFormat.setPaper(paper);
      
        printJob.getJobName().describeConstable();
        printJob.setJobName(jobName);
      
        printJob.setPrintable(prnt, pageFormat);
      
        try {
            printJob.print(set);
        } catch (PrinterException e) {
            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 static void disableDoubleBuffering( Component c ) {
        RepaintManager currentManager = RepaintManager.currentManager( c );
        currentManager.setDoubleBufferingEnabled( false );
    }


    public static void enableDoubleBuffering( Component c ) {
        RepaintManager currentManager = RepaintManager.currentManager( c );
        currentManager.setDoubleBufferingEnabled( true );
    }
  
}
In den Drucker-Einstellungen sowohl Lokal (Treiber) wie auch auf der Geräte-Webseite hat das "Mehrzweck Papierfach" als default ein C5-Medium und trotzdem wird das Y anhand eines (A4-Höhe / 2) - (C5-Breite / 2) im obigen Code, berechnet!

Wie schon in der Bibel steht:
Wissende vergebt mir, denn ich weiss NICHT was ich tu! 😁
(oder so ähnlich)

Sorry wieder ein PS:
LibreOffice, MasterPdf-Editor können das nach einmaligem Einstellen und Speichern.
Bei erneutem öffnen eines solchen Dokuments kann ich einfach auf Schnelldruck klicken und es Passt.
 
Zuletzt bearbeitet:

Zurück
Oben