Drucken mehrerer JTables als ein Job - Das Buchobjekt druckt nur die erste Tabelle

Aus verschiedenen Gründen versuche ich, die Ausgabe mehrerer JTables in einem einzigen Druckauftrag zu kombinieren. Nachdem ich mir die Haare ausgerissen hatte, PDFs zu erstellen und die Java-API zu kämmen, entschied ich mich für die Book-Klasse. Mein Druckcode sieht derzeit so aus.

try {       
    PrinterJob printer = PrinterJob.getPrinterJob();

    //Set 1/2 " margins and orientation
    PageFormat pf = printer.defaultPage();
    pf.setOrientation(PageFormat.LANDSCAPE);
    Paper paper = new Paper();
    double margin = 36; // half inch
    paper.setImageableArea(margin, margin, paper.getWidth() - margin * 2, paper.getHeight() - margin * 2);
    pf.setPaper(paper);

    Book printJob = new Book();

    // Note for next line: getAllTables() returns an ArrayList of JTables
    for (JTable t : getAllTables() )  
        printJob.append(t.getPrintable(PrintMode.FIT_WIDTH, null, null), pf,2);

    printer.setPageable(printJob);

    System.out.println(printJob.getNumberOfPages());

    if (printer.printDialog())
        printer.print();
    } catch (PrinterException e) {
        e.printStackTrace();
}

Hauptproblem: Es wird nur die Ausgabe der "ersten" Tabelle gedruckt. Ich habe dafür gesorgt, dass die for-Schleife korrekt durchläuft, und die Debugging-Anweisungen haben gezeigt, dass jede Tabelle dem Buch hinzugefügt wird. Das Ändern der Tabellenreihenfolge hat keine Auswirkungen. Ändern des Druckmodus aufPrintMode.NORMAL, erscheint und Teile der anderen Tabellen werden gedruckt. Ich habe jedoch Probleme mit der horizontalen Verschiebung, da die Tabellenbreite häufig die Seitenbreite überschreitet (und es immer noch nicht erklärt, warumPrintMode.FIT_WIDTH funktioniert nicht

Eine sekundäre Frage: Wie kann ich die richtige Anzahl von Seiten in jedem Ausdruck erkennen? Die meisten meiner Tabellen sind zwei Seiten lang, daher füge ich im Moment jedes Mal, wenn ich anhänge, nur zwei Seiten hinzu. Ich las "irgendwo" das mitBook.UNKNOWN_NUMBER_OF_PAGES da die Seitenzahl dieses Problem behebt, führt dies jedoch nur zu einer IndexOutOfBounds-Ausnahme im API-Code. Ich habe überlegt, Print selbst anzurufen, bis ich es bekommeNO_PAGE_EXISTS, aber ich brauche ein Grafikobjekt mit den richtigen Seitenabmessungen (und ich habe keine Ahnung, wie ich das bekommen kann).

Zuletzt: Wie kann ich die Ausgabe mehrerer JTables (dh mehrerer Ausdrucke) in einem einzigen Auftrag zusammenfassen, wenn der Book-Ansatz hoffnungslos ist? Ich habe nachgesehenExport der Tabelle als PDF, aber die eingebaute Paginierung von JTable ist so nett, dass ich es lieber nicht selbst machen müsste. Mein letzter Ausweg ist, einfach aufzugeben und die eingebaute Tabellenfunktion von iText zu verwenden, um eine Kopie der Tabelle zu erstellen.

Edit 3: Laut meinem Kommentar unten funktionierte dies, indem ich einen Ausdruck erstellte, die Anzahl der Seiten bestimmte und dann einen neuen erstellte. Ich habe auch Durendals Wrapper modifiziert, um uns den Aufwand zu ersparen, über jede Seite zu iterieren. Der Code aus dem Wrapper ist

    class PrintableWrapper implements Printable
    {
        private Printable delegate;
        private int offset;

        public PrintableWrapper(Printable delegate, int offset) {
            this.offset = offset;
            this.delegate = delegate;
        }

        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            return delegate.print(graphics, pageFormat, pageIndex-offset);
        }
    }   

Ich habe Durendals Code zur Bestimmung der Seitenzahl in eine eigene Funktion eingefügt

    public int getNumberOfPages(Printable delegate, PageFormat pageFormat) throws PrinterException 
    {
        Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
        int numPages = 0;
        while (true) {
            int result = delegate.print(g, pageFormat, numPages);
            if (result == Printable.PAGE_EXISTS) {
                ++numPages;
            } else {
                break;
            }
        }

        return numPages;
    }

Nachdem ich das Buchobjekt erstellt habe, sieht mein Druckcode folgendermaßen aus

            int totalPages = 0;
            for (DragNDropTable t : getAllTables() )
            {
                int pages = getNumberOfPages(t.getPrintable(PrintMode.FIT_WIDTH, null, null), pf);
                Printable p = t.getPrintable(PrintMode.FIT_WIDTH, null, null);
                printJob.append(new PrintableWrapper(p,totalPages), pf, pages);
                totalPages += pages;
            }
            printer.setPageable(printJob);

            if (printer.printDialog())
                printer.print();

Und es funktioniert wie ein Zauber!

Edit 2: (Sie können dies überspringen) Ich habe Durendals Antwort ausprobiert. Während ich genügend Seiten drucke, drucken mehrseitige Ausdrucke die letzte Seite mehrmals (einmal für jede Seite im Ausdruck). Dies ist das gleiche Problem, das ich in meiner ersten Ausgabe (unten) besprochen habe, und ich habe keine Ahnung, warum dies geschieht, und meine Debug-Anweisungen besagen, dass alle Seiten korrekt gedruckt werden, aber die letzte Seite eines mehrseitigen Ausdrucks gedruckt wird anstelle jeder Seite. Code ist beigefügt. Einblick wird geschätzt (und mit virtuellen Cookies zurückgezahlt)

try {       
    PrinterJob printer = PrinterJob.getPrinterJob();

    //Set 1/2 " margins and orientation
    PageFormat pf = printer.defaultPage();
    pf.setOrientation(PageFormat.LANDSCAPE);
    Paper paper = new Paper();
    double margin = 36; // half inch
    paper.setImageableArea(margin, margin, paper.getWidth() - margin * 2, paper.getHeight() - margin * 2);
    pf.setPaper(paper);

    Book printJob = new Book();

    // Note for next line: getAllTables() returns an ArrayList of JTables
    for (JTable t : getAllTables() )  
    {
        Printable p = t.getPrintable(PrintMode.FIT_WIDTH, null, null);
        int pages = getNumberOfPages(p, pf);

        for (int i=0; i < pages; i++)
            printJob.append(new PageWrapper(p,i), pf);
    }

    printer.setPageable(printJob);

    System.out.println(printJob.getNumberOfPages());

    if (printer.printDialog())
        printer.print();
    } catch (PrinterException e) {
        e.printStackTrace();
}

public int getNumberOfPages(PageFormat pageFormat) throws PrinterException 
{
    Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
    int numPages = 0;
    while (true) {
        int result = delegate.print(g, pageFormat, numPages);
        if (result == Printable.PAGE_EXISTS) 
            ++numPages;
        else
            break;
    }

    return numPages;
}

Ich verwende den unveränderten PageWrapper, den Durendal unten angegeben hat.

Edit 1: (Sie können dies überspringen) Ausgehend von Durendals Antwort habe ich versucht, einen Umschlag zu erstellen, der uns die Mühe erspart, die Seiten selbst zu durchlaufen. Leider scheint es bei mehrseitigen Ausdrucken nicht richtig zu funktionieren, da dieselbe Seite im Dokument mehrmals gedruckt wird. Ich poste es, einfach weil jemand es zum Laufen bringen könnte und es etwas bequemer zu benutzen ist.

class PrintableWrapper implements Printable
    {
        private Printable delegate;
        private int offset;

        public PrintableWrapper(Printable delegate, int offset) {
            this.offset = offset;
            this.delegate = delegate;
        }

        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            return delegate.print(graphics, pageFormat, pageIndex-offset);
        }


        public int getNumberOfPages(PageFormat pageFormat) throws PrinterException 
        {
            Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
            int numPages = 0;
            while (true) {
                int result = delegate.print(g, pageFormat, numPages);
                if (result == Printable.PAGE_EXISTS) 
                    ++numPages;
                else
                    break;
            }

            return numPages;
        }
    }

Mein Druckcode sieht jetzt so aus (nachdem ich das Seitenformat eingestellt habe)

Book printJob = new Book();
int totalPages = 0;

for (DragNDropTable t : getAllTables() )
{
    Printable p = t.getPrintable(PrintMode.FIT_WIDTH, null, null);
    PrintableWrapper pw = new PrintableWrapper(p, totalPages);
    totalPages += pw.getNumberOfPages(pf);
    printJob.append(pw, pf,pw.getNumberOfPages(pf));
}

printer.setPageable(printJob);

if (printer.printDialog())
{
    printer.print();

}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage