Z wielu powodów próbuję połączyć wyjście wielu JTables w jedno zadanie drukowania. Po rozerwaniu włosów, próbując zbudować pliki PDF i przeczesując Java API, zdecydowałem się na klasę Book. Mój kod drukowania wygląda obecnie tak.Drukowanie wielu JTables jako jednego zadania - Obiekt książki tylko drukuje pierwszą tabelę
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();
}
Podstawowy problem: Tylko wyjście z "pierwszej" tabeli jest druk. Upewniłem się, że pętla for iteruje poprawnie, a instrukcje debugowania pokazały, że każda tabela jest dodawana do Księgi. Zmiana kolejności tabel nie ma żadnego wpływu. Zmiana trybu drukowania na PrintMode.NORMAL
powoduje wyświetlenie pozostałych wydrukowanych tabel. Ja jednak napotkasz mnóstwo poziomych problemów paginacji, jak szerokość tabeli często przekracza szerokość strony (i to nadal nie wyjaśnia, dlaczego PrintMode.FIT_WIDTH
nie działa)
Pytanie wtórny: W jaki sposób można wykryć poprawne liczba stron w każdym druku? Większość moich tabel ma dwie strony, więc na razie dodam po prostu 2 strony za każdym razem, gdy dołączam. Przeczytałem "gdzieś", że użycie numeru Book.UNKNOWN_NUMBER_OF_PAGES
naprawi ten problem, ale spowoduje to jedynie wyjątek IndexOutOfBounds w kodzie API. Rozważałem wywoływanie druku, dopóki nie otrzymam NO_PAGE_EXISTS
, ale potrzebuję obiektu Graphics z odpowiednimi wymiarami strony (i nie mam pojęcia, jak to uzyskać).
Wreszcie: Jeśli podejście Książka jest beznadziejna, jak inaczej mogę połączyć wyjście wielu JTables (np. Wielu drukarek) w jedno zadanie? Zajrzałem do exporting the table as a PDF, ale wbudowana pagina JTable jest tak dobra, że wolałabym nie robić tego sama. Ostatnią rzeczą jest po prostu zrezygnować i użyć wbudowanej funkcji tabeli iText do skonstruowania kopii tabeli.
Edit 3: Na moim komentarzu poniżej, dostałem tej pracy przez generowanie wydruku, ustalania # stron, a następnie wygenerowanie nowego. Zmodyfikowałem także opakowanie Durendala, aby zaoszczędzić nam kłopotów z iteracją po każdej stronie. Kod z opakowania jest
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);
}
}
umieścić kod Durendal dla określenia liczby stron w swojej własnej funkcji
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;
}
Po utworzeniu obiektu książce, mój kod druk wygląda to
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();
I działa jak urok!
Edytuj 2: (możesz to pominąć) Próbowałem odpowiedzi Durendala. Podczas drukowania wystarczającej liczby stron, wielostronicowe wydruki drukują ostatnią stronę wiele razy (raz dla każdej strony w druku). To jest ten sam problem, który omówiłem w mojej pierwszej edycji (poniżej) i nie mam pojęcia, dlaczego tak się dzieje, a moje oświadczenia dotyczące debugowania mówią, że poprawnie drukuje wszystkie strony, ale drukuje się ostatnia strona wydruku wielostronicowego w miejsce każdej strony. Kod jest załączony. Insight jest doceniana (i spłacili z wirtualnymi ciasteczka)
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;
}
Używam niezmodyfikowanej PageWrapper że Durendal dał poniżej.
Edytuj 1: (Możesz to pominąć) Wychodząc od odpowiedzi Durendala, próbowałem zrobić opakowanie, które oszczędza nam trudu, by samemu przeglądać strony. Niestety nie działa poprawnie w przypadku drukarek wielostronicowych, wielokrotnie drukuje tę samą stronę w dokumencie. Publikuję to, ponieważ ktoś może go uruchomić i jest nieco wygodniejszy w użyciu.
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;
}
}
Mój kod druk teraz wygląda następująco (po tym, jak ustawić format strony)
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();
}
Doskonała prezentacja pytania i odpowiedzi. Miałem ten sam problem i mogłem odtworzyć to rozwiązanie krok po kroku. Bardzo dobre poprawki autorstwa @kleopatra. – downeyt