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

发布于 2024-11-18 04:58:25 字数 715 浏览 2 评论 0原文

如果我在实现 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,假设我能以某种方式知道页面被渲染了两次。)

If I do this in my class that implements 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();
    } 
}

it works, but my Printable class gets print() called twice. (presumably for resource allocation purposes by the printer driver)

How can I display a progress bar properly? In my case, I know how many sub-printing tasks need to execute, but if I try to display it, the progress bar will proceed from start to finish twice, which is horrible feedback for a user. And I'd rather not display an indeterminate progress bar....

What should I do?


clarification: I'm printing a bunch of plots on a page. They're somewhat intricate and take a while to print, so I might know that there's 10 objects to render, so I'd like to have my progress bar go from 0 to 10, and increment it after I render each of the 10 objects. (Or, even better, go from 0 to 20, assuming I could somehow know the page was being rendered twice.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把梦留给海 2024-11-25 04:58:25

查看提供给 print 方法的参数,第一次调用它(至少对我来说),图形是 PeekGraphics 对象,第二次是 WPathGraphics 对象。在我的系统上, RasterPrinterJob 正在创建一个 PeekGraphics 以获取有关在为实际打印作业设置图形之前先打印作业。

根据您更新进度条的方式,您可能可以在勾选之前检查图形参数是否不是 PeekGraphics。

Looking at the arguments supplied to the print method, the first time it's called (for me at least), the graphics is a PeekGraphics object, and the second time is a WPathGraphics one. On my system, RasterPrinterJob is creating a PeekGraphics to get information about the print job before setting up the graphics for the real print job.

Depending on how you're updating your progress bar, you might be able to just check that the graphics argument is not a PeekGraphics before you give it a tick.

太阳公公是暖光 2024-11-25 04:58:25

我放弃了尝试预测或区分 print() 调用次数的想法。

@Atreys 的答案很有希望,但我可以使用不反射或导入私有 sun.* 类的唯一区别是 sun.print.PeekGraphics 实现 java.awt.image.ImageObserver,而 sun.awt.windows.WPathGraphics 则不然。 (getClass().getName() 在我的书中算作反射)

我最终所做的是对 Printable.print() 的每个单独调用使用进度条,例如将进度重置为开始并推进打印的每个子步骤。

为了防止用户抱怨进度条显示两次进度,每当调用 print() 时,我都会将标签更改为“Pass #{k}”,其中 {k} 是每次都会递增的计数器。


ps 从 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;
}

I gave up on the idea of trying to predict or distinguish the # of calls to print().

@Atreys' answer was promising, but the only difference that I could use w/o reflection or importing private sun.* classes was that sun.print.PeekGraphics implements java.awt.image.ImageObserver, whereas sun.awt.windows.WPathGraphics does not. (getClass().getName() counts as reflection in my book)

What I ended up doing was to use my progress bar for each individual call to Printable.print(), e.g. reset the progress to the beginning and advance it for each substep of print.

To keep the users from complaining that the progress bar shows progress twice, I have a label that is changed to "Pass #{k}" whenever print() is called, where {k} is a counter that is incremented each time.


p.s. The proper way to cancel a print job from within Printable.print() is a little tricky. Throwing PrintAbortException doesn't seem to work correctly, as it ends the call to print() but the printer driver keeps going, despite the fact that the Printable javadoc says this:

If the Printable object aborts the print job then it throws a PrinterException.

Instead, you have to cast the print() method's Graphics parameter as a PrintGraphics object, and then call 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文