いくつかの理由から、複数の JTable の出力を 1 つの印刷ジョブに結合しようとしています。PDF を構築しようとして頭を悩ませ、Java API をくまなく調べた後、私は Book クラスに落ち着きました。現在、私の印刷コードは次のようになっています。
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();
}
主な問題:「最初の」テーブルからの出力のみが印刷されます。for ループが正しく繰り返されることを確認しました。デバッグ ステートメントは、すべてのテーブルが Book に追加されていることを示しています。テーブルの順序を変更しても効果はありません。印刷モードを に変更するPrintMode.NORMAL
と、他の表の断片が印刷されるようになります。ただし、テーブルの幅がページの幅を頻繁に超えるため、水平方向のページネーションの問題が多数発生します (なぜ機能しないのかPrintMode.FIT_WIDTH
はまだ説明されていません) 。
二次的な質問:各印刷物の正確なページ数を検出するにはどうすればよいですか? 私のテーブルのほとんどは 2 ページの長さなので、今のところ、追加するたびに 2 ページだけ追加しています。ページ番号として使用するとこの問題が解決することを「どこか」で読みBook.UNKNOWN_NUMBER_OF_PAGES
ましたが、それは API のコードで IndexOutOfBounds 例外につながるだけです。が得られるまで print を自分で呼び出すことを検討しましNO_PAGE_EXISTS
たが、適切なページサイズの Graphics オブジェクトが必要です (それを取得する方法がわかりません)。
最後に: Book アプローチが絶望的である場合、複数の JTables (つまり、複数の印刷可能なもの) の出力を 1 つのジョブに結合するにはどうすればよいでしょうか? テーブルを PDF としてエクスポートすることを検討しましたが、JTable の組み込みのページネーションは非常に優れているため、自分で行う必要はありません。私の最後の手段は、あきらめて iText の組み込みテーブル関数を使用してテーブルのコピーを作成することです。
編集 3:以下の私のコメントによると、印刷可能なページを生成し、ページ数を決定してから、新しいページを生成することで、これを機能させました。また、Durendal のラッパーを修正して、各ページを繰り返し処理する手間を省きました。ラッパーのコードは
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(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;
}
book オブジェクトを作成すると、印刷コードは次のようになります
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();
そして、それは魅力のように機能します!
編集 2: (これをスキップできます) Durendal の回答を試しました。十分なページを印刷している間に、複数ページの印刷可能ファイルが最後のページを複数回印刷しています (印刷可能ページごとに 1 回)。これは、最初の編集 (以下) で説明したのと同じ問題です。なぜこれが起こっているのかわかりません。デバッグ ステートメントでは、すべてのページが正しく印刷されていると言っていますが、複数ページの印刷可能なページの最後のページが印刷されます。各ページの代わりに。コードが付属しています。洞察は高く評価されます (そして、仮想 Cookie で報われます)
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;
}
Durendal が以下に示した変更されていない PageWrapper を使用しています。
編集 1: (これはスキップできます) Durendal の回答に合わせて、自分でページを繰り返し処理する手間を省くラッパーを作成しようとしました。残念ながら、ドキュメント内で同じページを複数回印刷する複数ページの印刷物では正しく機能しないようです。誰かがそれを機能させる可能性があるという理由だけで、私はそれを投稿しました。
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;
}
}
私の印刷コードは次のようになりました(ページ形式を設定した後)
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();
}