AWT eine Seite - zweimal print()

kodela

Bekanntes Mitglied
Hallo,

ich habe heute ein Problem mit dem Ausdruck von Seiten mit Sudoku-Aufgaben, das ich mit folgenden beiden Test-Klassen aufzeigen will.

Gleich vorweg, der Ausdruck funktioniert einwandfrei. Allerdings geschieht hier etwas, was ich nicht verstehe.

Also hier einmal der Code, zuerst für die Klasse mit der main()-Methode:

Java:
package sdkprinttest;

import java.util.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;

public class SdkPrintTest {
    private int seiten;

    public boolean prinSdktSerie(String[][] info) {
        seiten = (info.length + 3) / 4;
        DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        aset.add(new MediaPrintableArea(6, 6, 198, 285, MediaPrintableArea.MM));
        aset.add(MediaSizeName.ISO_A4);

        try {
            PrintService prservDflt = PrintServiceLookup.lookupDefaultPrintService();
            PrintService[] prservices = PrintServiceLookup.lookupPrintServices(flavor, aset);
            if (prservices == null || prservices.length <= 0) {
                if (prservDflt != null) {
                    prservices = new PrintService[]{prservDflt};
                } else {
                    return false;
                }
            }
            PrintService prserv = PrintServiceLookup.lookupDefaultPrintService();
            if (!Arrays.asList(prservices).contains(prservDflt)) {
                prservDflt = null;
            }
            if (prserv != null) {
                PrintSdkSeite sdkSeite = new PrintSdkSeite(info);
                for (int s = 0; s < seiten; s++) {
                    DocPrintJob pj = prserv.createPrintJob();
                    Doc doc = new SimpleDoc(sdkSeite, flavor, null);
                    pj.print(doc, aset);
                }
            }
            else return false;
        } catch (PrintException pe) {
            return false;
        }
        return true;
    }
    @SuppressWarnings("ResultOfObjectAllocationIgnored")
    public static void main(String args[]) {
        String daten[][] = {
            {"1001",
                ".6.3......25..7..9....5............2.478.......2743.5........1..8..6...37.9...82.",
                "4 (24.002)"},
            {"1002",
                ".41.7..2..8.....4.....69...8..51...2..3.9..1.2...3.6...6..............819.2...7..",
                "4 (24.002)"},
            {"1003",
                ".....4...7..1....8.3..89......578.64.5.6....39......8......6.....2.3.65..6.8..37.",
                "4 (26.003)"},
            {"1004",
                "....8...4..1...69.4.....3.8...7...8.7....61....93.......4.37..5.1.2...6.3..6.....",
                "4 (24.003)"},
            {"2001",
                ".6.3......25..7..9....5............2.478.......2743.5........1..8..6...37.9...82.",
                "4 (24.002)"},
            {"2002",
                ".41.7..2..8.....4.....69...8..51...2..3.9..1.2...3.6...6..............819.2...7..",
                "4 (24.002)"},
            {"2003",
                ".....4...7..1....8.3..89......578.64.5.6....39......8......6.....2.3.65..6.8..37.",
                "4 (26.003)"},
            {"2004",
                "....8...4..1...69.4.....3.8...7...8.7....61....93.......4.37..5.1.2...6.3..6.....",
                "4 (24.003)"},
            {"0005",
                "2....5.9.17..........1..7..7...1..6...824...3..9.......9.7...2....8...3.6..3....4",
                "4 (23.010)"},
            {"0006",
                "..7..8.9.....4.3..3.8...4..4........7.5..98.2....125..6.37....4......6....2.8..5.",
                "4 (25.001)"},
            {"0007",
                "4....58...2..........2.4.753..5.....7.6..3...5......3429......1..16.........479..",
                "4 (24.003)"},
            {"0008",
                ".3.4.96..4.....31....7.......82.31....5..6...6.1.9.2...59.8.......94....2......83",
                "4 (26.008)"}};

        SdkPrintTest pS = new SdkPrintTest();
        pS.prinSdktSerie(daten);
    }
}

und jetzt die Klasse, in der gedruckt wird:

Java:
package sdkprinttest;

import java.awt.*;
import java.awt.print.*;

public class PrintSdkSeite implements Printable {

    public static final int iResMul = 4;
    private static final Point[] POS = {
        new Point(0, 0),
        new Point(1190, 0),
        new Point(0, 1670),
        new Point(1190, 1670)};
    private static final int[] kWrt = {122, 236, 350, 468, 582, 696, 814, 928, 1042};
    private int anzahl;
    private int dSI;
    public String[] nDS = new String[3];
    private int pos;
    int pair;
    String[][] sdkInfo;

    public PrintSdkSeite(String[][] inf) {
        sdkInfo = inf;
        anzahl = sdkInfo.length;
        dSI = 0;
        pair = 0;
    }

    public int print(Graphics g, PageFormat pf, int iPage)
            throws PrinterException {

        int FONTSIZE;
        if (iPage != 0) {
            return NO_SUCH_PAGE;
        }
        if (++pair % 2 != 0) {
            return PAGE_EXISTS;
        }
        try {
            Graphics2D g2 = (Graphics2D) g;
            g2.translate(17, 17);
            g2.scale(1.0 / iResMul, 1.0 / iResMul);
            g.setColor(Color.black);
            for (pos = 0; pos < 4; pos++) {
                int x = POS[pos].x;
                int y = POS[pos].y;
                zeichneSdkFeld(g2, x, y);
                if (dSI < anzahl) {
                    nDS = sdkInfo[dSI++];
                    FONTSIZE = 12;
                    g.setFont(new Font("Arial", Font.PLAIN, FONTSIZE * iResMul));
                    setzeTitel(g2, x, y);
                    FONTSIZE = 18;
                    g.setFont(new Font("Arial", Font.BOLD, FONTSIZE * iResMul));
                    setzeWerte(g2, x, y);
                }
            }
        } catch (Exception ex) {
            throw new PrinterException(ex.getMessage());
        }
        return PAGE_EXISTS;
    }

    private void zeichneSdkFeld(Graphics g2, int x0, int y0) {
        // alle waagrechten Linien
        g2.fillRect(x0, y0 + 300, 1052, 10);
        g2.fillRect(x0, y0 + 422, 1052, 2);
        g2.fillRect(x0, y0 + 536, 1052, 2);
        g2.fillRect(x0, y0 + 650, 1052, 6);
        g2.fillRect(x0, y0 + 768, 1052, 2);
        g2.fillRect(x0, y0 + 882, 1052, 2);
        g2.fillRect(x0, y0 + 996, 1052, 6);
        g2.fillRect(x0, y0 + 1114, 1052, 2);
        g2.fillRect(x0, y0 + 1228, 1052, 2);
        g2.fillRect(x0, y0 + 1342, 1052, 10);
        // alle senkrechten Linien
        g2.fillRect(x0, y0 + 300, 10, 1052);
        g2.fillRect(x0 + 122, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 236, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 350, y0 + 300, 6, 1042);
        g2.fillRect(x0 + 468, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 582, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 696, y0 + 300, 6, 1052);
        g2.fillRect(x0 + 814, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 928, y0 + 300, 2, 1052);
        g2.fillRect(x0 + 1042, y0 + 300, 10, 1052);
    }

    private void setzeTitel(Graphics g2, int x0, int y0) {
        if (nDS == null) {
            return;
        }
        g2.drawString("SUDOKU A"
                + nDS[0] + " - Level "
                + nDS[2], x0 + 150, y0 + 180);
    }

    private void setzeWerte(Graphics g2, int x0, int y0) {
        if (nDS == null) {
            return;
        }
        String aufgabe = nDS[1];
        for (int i = 0; i <= 80; i++) {
            char w = aufgabe.charAt(i);
            if (w == '.') {
                continue;
            }
            g2.drawString("" + w, x0 + kWrt[i % 9] - 76, y0 + kWrt[i / 9] + 272);
        }
    }
}

Mein Problem liegt darin, dass das Ganze nur funktioniert, wenn ich in der Klasse PrintSdKSeite mit folgendem Code dafür sorge, dass print() bei einem ersten Aufruf für eine Seite sofort mit PAGE_EXISTS wieder beende.

[JAVA=36]
if (++pair % 2 != 0) {
return PAGE_EXISTS;
}
[/code]

Weiß jemand, welcher Fehler in meinem Code dafür ursächlich ist.

Schon im Voraus herzlichen Dank für das Interesse an meinem Problem.

kodela
 
Kleiner Nachtrag:

Mittlerweile habe ich gesehen, dass schon einmal jemand hier wegen des selben Problems eine Frage gestellt hat. Die Antworten dazu sind aber wenig hilfreich, denn es ist ja nicht so, zu mindest bei mir, dass dieser zweimalige Aufruf von print() keine Auswirkungen hätte.

Da in meiner print()-Methode (und vermutlich bei anderen auch) ja jedes Mal eine neue Seite gezeichnet wird, wird immer nur jede zweite Seite ausgedruckt. Das ist ja wohl nicht das Gelbe vom Ei.

Ich habe trotz langer Suche auch noch in keiner Dokumentation einen Hinweis darauf gefunden, dass print() sich so eigenartig verhält.

Noch eine Frage am Rande. Wie bringt ihr es fertig, dass der Betreff zu einem Thread fett gedruckt wird. Bei mir sind die immer nur "mager". Bisher habe ich den Nippel, durch den die Lasche zu ziehen ist, noch nicht gefunden.

kodela
 
fett gedruckt werden Themen, in denen Beiträge stehen, die du noch nicht gelesen hast,
das ist eine temporäre Darstellung für jeden User einzeln

wie sich das Forum das für tausende User auch über Jahre blitzschnell merkt, ist mir allerdings auch eher ein Rätsel
 
Wenn das (bei mir) so wäre, dann hätte ich dies sicher längst bemerkt. Ich bin mir aber absolut sicher, dass auch Beiträge, die ich gelesen habe, der Betreff, wenn er vorher fett war, auch nachher noch fett ist. Sicherheitshalber habe ich eben noch einmal die Probe aufs Exempel gemacht. Fette sind und bleiben bei mir fett.

kodela
 
Moin,

weiß hier wirklich niemand, warum print() zweimal für eine Seite aufgerufen wird?

nicht mehr so genau, aber bei mir ist es auch so!
Ich habe mir damals als Kommentar dran geschrieben, dass der erste Aufruf "den Druck nur vorbereitet" und erst der zweite das eigentlich Drucken durchführt. Ich meine, dass beim Vorbereiten die Anzahl der Druckseiten über die Seitengröße berechnet wird!

Gruß
Klaus
 
Hallo Klaus,

Du schreibst:
Ich habe mir damals als Kommentar dran geschrieben, dass der erste Aufruf "den Druck nur vorbereitet" und erst der zweite das eigentlich Drucken durchführt. Ich meine, dass beim Vorbereiten die Anzahl der Druckseiten über die Seitengröße berechnet wird!
Nach meinen Feststellungen geschieht im ersten Aufruf nichts was irgend wie relevant wäre. Wie man an meinem Beispiel sehen kann, folgt auf jeden ersten Aufruf für eine Seite sofort ein return. Im zweiten Aufruf wird dann die Seite gezeichnet und anschließend ausgedruckt. Wenn beim ersten Aufruf der Druck vorbereitet würde, was immer darunter zu verstehen ist, dann dürfte mein Beispiel nicht funktionieren. Es funktioniert aber, obwohl ich print() nicht ermögliche, irgend etwas zu tun.

kodela
 
Hallo,

sogar in einem Tutorial zum Thema Drucken mit Jafa fand ich ein Beispiel, mit dem eine Testseite zweimal gezeichnet und einmal ausgedruckt wird. Solange man nicht genau überprüft, was der Code macht, fällt es nicht auf, dass auch dieses Beispiel die Testseite zweimal zeichnet und einmal ausdruckt. Verändert man die Testseite bei jedem Zeichnen etwas, z.B. durch einen mitlaufenden Seiten-Zähler, stellt man fest, dass nur die zweite gezeichnete Seite ausgedruckt wird.

Ich gehe davon aus, dass die Entwickler von Java das so weder gewollt noch "verbrochen" haben. Nach meiner festen Überzeugung bin ich es, der hier etwas falsch macht und niemand kann mir anscheinend sagen, was ich falsch mache. Auch der Autor des erwähnten Tutorials schweigt sich aus.

Fazit für mich: Mein Code, der nur bei jedem zweiten Aufruf von print() eine Seite zeichnet, muss so bleiben wie er ist. Damit funktioniert er einwandfrei.

kodela
 

Zurück
Oben