如何在Swing中显示打印进度对话框?

时间:2011-07-04 18:37:22

标签: java swing user-interface printing progress-bar

如果我在实现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()调用两次。 (可能是出于打印机驱动程序的资源分配目的)

如何正确显示进度条?在我的情况下,我知道需要执行多少个子打印任务,但是如果我尝试显示它,则进度条将从头到尾两次进行,这对于用户来说是可怕的反馈。而且我宁愿不显示不确定的进度条....

我该怎么办?


澄清:我在页面上打印了一堆图。它们有点错综复杂,需要一段时间来打印,所以我可能知道有10个对象要渲染,所以我想让我的进度条从0到10,并在渲染10个对象中的每一个后递增它。 (或者,更好的是,从0到20,假设我可以知道页面被渲染两次。)

2 个答案:

答案 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;
}