T. *_*K. 5 java printing swing jtable
出于多种原因,我正在尝试将多个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();
}
Run Code Online (Sandbox Code Playgroud)
主要问题:只有"第一个"表的输出才会打印.我已经确保for循环正确迭代,并且调试语句已经显示每个表都被添加到Book中.更改表的顺序无效.将打印模式更改为PrintMode.NORMAL,确实会出现打印其他表格的部分.但是,由于表格宽度经常超出页面宽度(我仍然无法解释为什么PrintMode.FIT_WIDTH不工作),因此我遇到了一个水平的分页问题.
第二个问题:如何在每个可打印中检测到正确的页数?我的大多数表都是两页长,所以目前我每次添加时都会添加2页.我读到"某个地方",使用Book.UNKNOWN_NUMBER_OF_PAGES页码将解决这个问题,但这只会导致API代码中的IndexOutOfBounds异常.我考虑过打印自己,直到我得到NO_PAGE_EXISTS,但我需要一个具有正确页面尺寸的Graphics对象(我不知道如何得到它).
最后:如果Book方法没有希望,我怎样才能将多个JTable(即多个printables)的输出合并到一个作业中?我考虑将表格导出为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);
}
}
Run Code Online (Sandbox Code Playgroud)
我把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;
}
Run Code Online (Sandbox Code Playgroud)
创建图书对象后,我的打印代码如下所示
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();
Run Code Online (Sandbox Code Playgroud)
它就像一个魅力!
编辑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;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
我的打印代码现在看起来像这样(在我设置页面格式之后)
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();
}
Run Code Online (Sandbox Code Playgroud)
我最近遇到了同样的问题。Book 类本身是无用的,因为如果向其中添加 Printable,当打印 Book 时,它会将 Book 的 pageIndex 传递到 pageIndex 处的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您需要遍历每个 Printable/Pageable 的每个页面,并向 Book 添加一个包装器实例(知道其委托中的 pageIndex)。这解决了 Book 将错误的 pageIndex 传递给添加到其中的可打印文件的问题(对于可打印文件来说,它比可打印文件更容易)。
您可以通过打印来检测可打印文件中的页数;)是的,我是认真的:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
从要打印到的实际 PrinterJob 获取 PageFormat 实例非常重要,因为页数取决于页面格式(纸张尺寸)。