由于多种原因,我正在尝试将多个JTable的输出组合到一个打印作业中。在尝试构建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页。我读到“某处”使用Book.UNKNOWN_NUMBER_OF_PAGES
作为页码将解决此问题,但这只会导致API代码中的IndexOutOfBounds异常。我考虑过打印自己,直到我得到NO_PAGE_EXISTS
,但我需要一个具有正确页面尺寸的Graphics对象(我不知道如何获得)。
最后:如果Book方法没有希望,我怎样才能将多个JTable(即多个printables)的输出合并到一个作业中?我查看了exporting the table as a 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);
}
}
我把Durendal的代码用于确定自己函数中的页数
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;
}
创建图书对象后,我的打印代码如下所示
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的回答。当我打印足够多的页面时,多页打印正在多次打印最后一页(对于可打印的每页打印一次)。这是我在第一次编辑(下面)中讨论过的同样的问题,我不知道为什么会发生这种情况,我的调试声明说它正确地打印了所有页面,但打印了多页打印的最后一页代替每一页。代码附后。洞察力受到赞赏(并通过虚拟饼干偿还)
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();
}
答案 0 :(得分:3)
我最近遇到了同样的问题。 Book类本身就是无用的,因为如果你向它添加Printables,当Book被打印时,它会将bookIndex从Book传递给pagetable索引的Printable。
在大多数情况下,这不是你想要的。
创建一个简单的Printable Wrapper,它可以记住要用于Printable委托的pageIndex并将它们添加到Book:
class PageWrapper implements Printable {
private Printable delegate;
private int localPageIndex;
public PageWrapper(Printable delegate, int pageIndex) {
this.localPageIndex = pageIndex;
this.delegate = delegate;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
return delegate.print(graphics, pageFormat, localPageIndex);
}
}
现在,您需要遍历每个Printable / Pageable的每个页面,并向Book中添加一个包装器实例(知道pageIndex到其委托中)。这解决了Book将错误的pageIndex传递给添加到其中的printables的问题(对于Pageables比Printables更容易)。
您可以通过打印来检测Printable中的页数;)是的,我是认真的:
Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
int numPages = 0;
while (true) {
int result = printable.print(g, pageFormat, numPages);
if (result == Printable.PAGE_EXISTS) {
++numPages;
} else {
break;
}
}
重要的是,您要从要打印的实际PrinterJob中获取PageFormat实例,因为页数取决于页面格式(纸张大小)。