如果我在实现Printable的类中执行此操作,
PrinterJob job = PrinterJob.getPrinterJob();
job.setJobName( /* some name */ );
Book book = new Book();
book.append(this, new PageFormat());
job.setPageable(book);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
}
catch (PrinterException ex) {
ex.printStackTrace();
}
}
它可以工作,但是我的Printable类会被print()
调用两次。 (可能是出于打印机驱动程序的资源分配目的)
如何正确显示进度条?在我的情况下,我知道需要执行多少个子打印任务,但是如果我尝试显示它,则进度条将从头到尾两次进行,这对于用户来说是可怕的反馈。而且我宁愿不显示不确定的进度条....
我该怎么办?
答案 0 :(得分:3)
查看提供给print方法的参数,第一次调用它(至少对我而言),图形是PeekGraphics对象,第二次是WPathGraphics对象。在我的系统上,RasterPrinterJob
正在创建PeekGraphics,以便在为实际打印作业设置图形之前获取有关打印作业的信息。
根据您更新进度条的方式,您可以在勾选之前检查图形参数是否不是PeekGraphics。
答案 1 :(得分:1)
我放弃了尝试预测或区分print()调用次数的想法。
@Atreys的答案很有希望,但我可以使用w / o反射或导入私有sun.*
类的唯一区别是sun.print.PeekGraphics
实现了java.awt.image.ImageObserver
,而sun.awt.windows.WPathGraphics
} 才不是。 (getClass()。getName()在我的书中计算为反射)
我最终做的是为Printable.print()
的每个电话使用我的进度条,例如将进度重置为开头,并为每个打印子步骤前进。
为了防止用户抱怨进度条显示两次进度,每当调用print()时,我都会将标签更改为“Pass#{k}”,其中{k}是一个递增的计数器时间。
P.S。从Printable.print()
内取消打印作业的正确方法有点棘手。抛出PrintAbortException似乎无法正常工作,因为它结束了对print()的调用,但打印机驱动程序继续运行,尽管Printable
javadoc说明了这一点:
如果Printable对象中止打印作业,则抛出PrinterException。
相反,您必须将print()方法的Graphics参数转换为PrintGraphics对象,然后调用PrintGraphics.getPrinterJob()。cancel():
if (graphics instanceof PrinterGraphics)
{
PrinterGraphics pg = (PrinterGraphics) graphics;
pg.getPrinterJob().cancel();
}
else
{
// this is kind of an unexpected circumstance
// not sure if we should do this or throw IllegalStateException()
PrinterAbortException pae = new PrinterAbortException();
pae.initCause(/* something */);
throw pae;
}