有没有在 Swing 应用程序中保留打印机设置的好方法?

发布于 2024-10-04 06:55:18 字数 2983 浏览 0 评论 0原文

我们正在使用新的 Java 打印 API,它使用 PrinterJob.printDialog(attributes) 向用户显示对话框。

想要下次保存用户的设置,我想这样做:

PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
if (printJob.printDialog(attributes)) {
    // print, and then...

    saveAttributesToPreferences(attributes);
}

但是,通过这样做我发现有时(我还没有弄清楚如何)属性内部会得到一些错误的数据,然后当当你打印时,你会得到一张没有任何内容的白页。然后,代码将中毒的设置保存到首选项中,并且所有后续的打印运行也会得到中毒的设置。此外,使新运行的设置与用户为上一次运行选择的设置相同的整个练习点都失败了,因为新对话框似乎没有使用旧设置。

所以我想知道是否有适当的方法来做到这一点。当然,Sun 并不希望用户每次启动应用程序时都必须选择打印机、页面大小、方向和边距设置。

编辑以显示存储方法的实现:

private PrintRequestAttributeSet loadAttributesFromPreferences()
{
    PrintRequestAttributeSet attributes = null;

    byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
    if (marshaledAttributes != null)
    {
        try
        {
            @SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
            ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));

            attributes = (PrintRequestAttributeSet) objectInput.readObject();
        }
        catch (IOException e)
        {
            // Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
            Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
        }
        catch (ClassNotFoundException e)
        {
            Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
        }
    }

    if (attributes == null)
    {
        attributes = new HashPrintRequestAttributeSet();
    }

    return attributes;
}

private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
{
    ByteArrayOutputStream storage = new ByteArrayOutputStream();
    try
    {
        ObjectOutput objectOutput = new ObjectOutputStream(storage);
        try
        {
            objectOutput.writeObject(attributes);
        }
        finally
        {
            objectOutput.close(); // side-effect of flushing the underlying stream
        }
    }
    catch (IOException e)
    {
        throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
    }

    preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
}

编辑:好吧,它不记得打印机的原因似乎是它不在 PrintRequestAttributeSet 中全部。事实上,边距和页面大小都会被记住,至少直到设置被随机中毒为止。但用户选择的打印机不在这里:

[0] = {java.util.HashMap$Entry@9494} class javax.print.attribute.standard.Media -> na-letter
[1] = {java.util.HashMap$Entry@9501} class javax.print.attribute.standard.Copies -> 1
[2] = {java.util.HashMap$Entry@9510} class javax.print.attribute.standard.MediaPrintableArea -> (10.0,10.0)->(195.9,259.4)mm
[3] = {java.util.HashMap$Entry@9519} class javax.print.attribute.standard.OrientationRequested -> portrait

We are using the new Java printing API which uses PrinterJob.printDialog(attributes) to display the dialog to the user.

Wanting to save the user's settings for the next time, I wanted to do this:

PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
if (printJob.printDialog(attributes)) {
    // print, and then...

    saveAttributesToPreferences(attributes);
}

However, what I found by doing this is that sometimes (I haven't figured out how, yet) the attributes get some bad data inside, and then when you print, you get a white page of nothing. Then the code saves the poisoned settings into the preferences, and all subsequent print runs get poisoned settings too. Additionally, the entire point of the exercise, making the settings for the new run the same as the user chose for the previous run, is defeated, because the new dialog does not appear to use the old settings.

So I would like to know if there is a proper way to do this. Surely Sun didn't intend that users have to select the printer, page size, orientation and margin settings every time the application starts up.

Edit to show the implementation of the storage methods:

private PrintRequestAttributeSet loadAttributesFromPreferences()
{
    PrintRequestAttributeSet attributes = null;

    byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
    if (marshaledAttributes != null)
    {
        try
        {
            @SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
            ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));

            attributes = (PrintRequestAttributeSet) objectInput.readObject();
        }
        catch (IOException e)
        {
            // Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
            Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
        }
        catch (ClassNotFoundException e)
        {
            Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
        }
    }

    if (attributes == null)
    {
        attributes = new HashPrintRequestAttributeSet();
    }

    return attributes;
}

private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
{
    ByteArrayOutputStream storage = new ByteArrayOutputStream();
    try
    {
        ObjectOutput objectOutput = new ObjectOutputStream(storage);
        try
        {
            objectOutput.writeObject(attributes);
        }
        finally
        {
            objectOutput.close(); // side-effect of flushing the underlying stream
        }
    }
    catch (IOException e)
    {
        throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
    }

    preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
}

Edit: Okay, it seems like the reason it isn't remembering the printer is that it isn't in the PrintRequestAttributeSet at all. Indeed, the margins and page sizes are remembered, at least until the settings get poisoned at random. But the printer chosen by the user is not here:

[0] = {java.util.HashMap$Entry@9494} class javax.print.attribute.standard.Media -> na-letter
[1] = {java.util.HashMap$Entry@9501} class javax.print.attribute.standard.Copies -> 1
[2] = {java.util.HashMap$Entry@9510} class javax.print.attribute.standard.MediaPrintableArea -> (10.0,10.0)->(195.9,259.4)mm
[3] = {java.util.HashMap$Entry@9519} class javax.print.attribute.standard.OrientationRequested -> portrait

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

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

发布评论

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

评论(1

圈圈圆圆圈圈 2024-10-11 06:55:18

看来您正在寻找的是 PrintServiceAttributeSet,而不是 PrintRequestAttributeSet

看一下 PrintServiceAttribute 接口,并查看您需要的元素是否已作为类实现。如果没有,您可以实现自己的 PrintServiceAttribute 类。

It appears that what you're looking for is the PrintServiceAttributeSet, rather than the PrintRequestAttributeSet.

Take a look at the PrintServiceAttribute interface, and see if the elements you need have been implemented as classes. If not, you can implement your own PrintServiceAttribute class(es).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文