Geertjan's Blog

  • September 11, 2007

Generating Print Previews of Swing Components on the NetBeans Platform

Geertjan Wielenga
Product Manager
It may seem counterintuitive that I am excited about this, after all my blogging about the joys of paperlessness, but there's something really cool that happened in the last few days on the NetBeans Platform—vastly enhanced and simplified print capabilities! :-) Not that I've actually printed anything as a result of this, seeing as I'm not connected to a printer because of aforementioned paperlessness. However, part of these enhancements include out-of-the-box support for a Print Preview dialog. That's come at an excellent time for me, since I've been studying Generating Print Preview of Swing Text Components in Sergey Groznyh's Blog. I created a small Java application, following Sergey's steps, and the result is very nice. But, setting up a Print Preview for Swing components is not exactly easy and on the NetBeans Platform it's not been any easier. In fact, it's always been harder, because one also had to (via the PrintCookie) enable the menu item as well. (What was even harder was finding out that this had to be done! The doing was relatively easy, but acquiring the knowledge that it was needed was tough!) And once it was enabled, one had to work with all the standard Swing printing functionality, just as one would with normal printing of Swing components.

However, all that is now in the past. Before showing the how, I'll first show you the what, so that you can see that taking the steps to set this up is a very worthwhile activity, both for NetBeans modules for the IDE as well as for NetBeans modules for any other application. Since I'm continually amazed by the beauty of Chet and Romain's samples, I'll use one of them as an example here. Below you see it, from the chapter on images, but this time on the NetBeans Platform:

You might be wondering what the point is of putting this sample "on the NetBeans Platform". There's clearly a whole bunch of buttons and menus that are not relevant for the sample, in the picture above. The sample should, one might think, simply stay a normal Java application and not be moved to a framework as large as the NetBeans Platform. Well, I have a lot of problems with that kind of reasoning, such as the fact that now that I have integrated it into the NetBeans Platform (which didn't take very long at all and I can continue pruning it, by removing the superfluous menu items and buttons, for example), it is part of a modular system that can be extended and hence is scalable. The original sample cannot be said to be scalable, by any definition of the word. However, let's leave that discussion for the moment and look at the File menu:

Notice that here we have a Print Preview menu item. And a Print menu item. Let's choose "Print Preview" and see what happens...

We now have a very expansive preview of what we are about to print. Expansive, in the sense that there is a lot of functionality here for tweaking our work prior to finally printing it. However, it's even better than you think, because when you click Options, in the picture above, you get this Options dialog, with even more functionality:

"Wow," you might be thinking at this point, "that must have taken a lot of work. Even if you used Matisse for laying out the GUIs, you still had to do a lot coding behind the scenes, to get everything working together correctly, to call the appropriate APIs, and so on." Well, what would you say if I told you that... this is all it took:

imagePanel.putClientProperty(java.awt.print.Printable.class, "");

All that happens is that the NetBeans Platform looks for JComponents with properties that are not null. Then it looks to see whether any of those has the key "java.awt.print.Printable.class" set. And then all the print functionality shown above is enabled for those components. The second argument to putClientProperty is a name, which is shown at the top of the print preview as the header, which can be changed by the user in the Options dialog. Above, I passed an empty name, so nothing is displayed above the image. One thing I don't like is that the developer can provide nothing other than the name, i.e., not colors, not fonts, not footers, not anything at all. However, the user is able to configure everything they want themselves, via the preview pane and the Options dialog, so maybe it's enough the way it is. All this is very new, from the last few days, so maybe things will still change and I'm hoping that more control will be given, optionally, to the developer, so that I can (but only if I want to) have more control over the default print preview. Also... would be nice if I could customize the Options dialog itself, although that might be too much to ask. However, would be cool if there were different layouts available and I could pass an argument to indicate which layout I would like (e.g., 'simple', 'medium', 'complex', or something along those lines).

But, no matter how you look at it, enabling print functionality for a Swing component could not possibly be simpler, now. With that one line you can enable printing for as many or as few of your components as you like. Does this mean that the NetBeans Platform has enhanced the standard Swing Printing API? Ummm... it sure looks like it, doesn't it? At the very least, all the complexity is hidden. As a developer, all you need to think about is WHICH component should be printable, not HOW that should be done. And that's the point of a framework—it provides all the common functionality that you typically need and you, as a client of the framework, simply need to enable/disable the functionality that is appropriate to you.

Currently, however, the modules that provide this functionality are not part of the cluster of modules that make up the NetBeans Platform. Instead, they belong to the 'soa' cluster. I'm hoping they'll move to the NetBeans Platform at some point before 6.0, although I don't know whether that will happen. So, if you are developing an application on the NetBeans Platform (as opposed to creating modules for the IDE, for which the following steps are not applicable since you simply need to install the IDE together with the 'soa' cluster, i.e., the 'full' IDE), to be able to enable print functionality for a JComponent, as shown above, you first need to go to your suite's Libraries panel, in the Project Properties dialog box. There, enable the 'soa' cluster, and then make sure that the Print module and the Print API module are both selected. Next, you will need to enable (if they are disabled) a few of the modules in the 'ide8' cluser, such as Editor Library, and three or four related modules, because these are needed (at least currently) by the Print module in the 'soa' cluster. And that's it, once you have these two modules as part of your suite, the Print menu item and Print Preview menu item will automatically be present, and they will be enabled for any JComponent that has the property shown above set for itself, which could also be a TopComponent, of course.

Hurray! Next I'm going to apply all this to the JFugue Music NotePad, because that's definitely an application that needs better print features! And here's the result, after adding the one line shown above, to the panel where the music sheet is located:

Do be aware, as stated above, that all this is new and formal announcements about this will be made, in due course, on the mailing lists and in the related javadoc.

In other news. Have a look at this interesting article about blogging: Write Articles, Not Blog Postings, by Jakob Nielsen.

Join the discussion

Comments ( 9 )
  • Peter Blemel Tuesday, September 11, 2007

    Good article, thanks.

    I see that the dialog has "number of pages". Where does it get this information, and how does it know what goes onto each page? Is there an interface that needs to be implemented for pagination?

    The print implementations that I have used are based on the AWT print classes PrinterJob and job.setPrintable(Pageable), in which the Pageable uses getPrintable(pageNo) to partition what goes onto a given printed page.

    The approach you've identified looks simpler, but it's not clear how to control what goes onto each page so the printouts look professional.

  • Vladimir Yaroslavskiy Wednesday, September 12, 2007

    Hi Peter Blemel,

    Print module takes a component and cuts it into pages based on print options (page height and width). You can't skip a piece of space or layout elements but you can try to do layout by changing print options.

    If you are advanced developer and wish to provide own pages, you should use interfaces from Print API: org.netbeans.modules.print.api/spi.

    There is interface PrintProvider which returns an array of PrintPage. To show Print Preview dialog with your implemented pages, just call PrintManagerAccess.getManager().print(yourPrintProvider, true).

    Let me know if you have any questions/comments.


    Vladimir Yaroslavskiy


    The owner of Printing

  • Tom Wheeler Wednesday, September 12, 2007

    Where can I find documentation of the new print API? I don't see a mention of PrintManagerAccess in the latest javadoc set, and clicking the "docs" link on print.netbeans.org (http://print.netbeans.org/docs.html) gives a page not found error.

    I'd really like to learn more about what support the NetBeans platform offers for printing.

  • Vladimir Yaroslavskiy Thursday, September 13, 2007

    Print API is being modified and improved. Docs will be added after stable version.

  • Peter Blemel Thursday, September 13, 2007

    > just call PrintManagerAccess.getManager().print(yourPrintProvider, true).

    If PrintCookie is now effectively ignored, then how does one make this call? Do we need to add our own PrintAction and hide the (previously functional) print action?

  • Wadi Wednesday, October 17, 2007

    Hi Greetjan! First of all the article is excelent. I would like to know wich version of netbeans did you use cause I'm having trouble with this, I couldn find the Print Api module and the actions are not enable. Anyway,Thanks in advance

  • Geertjan Wielenga Thursday, June 17, 2010
  • guest Tuesday, June 14, 2011

    Is there any documentation for using this functionality with tables/scrollpanes? The preview only shows visible area.

  • guest Friday, October 16, 2015


    if it is possible, would u helpe with the example code java that u used

    for this compenent

    thank u

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.