I’ve written a class and some supporting functions that will allow me to print multiple charts as a single print job.
The basic process consists of printing the windows to image files, reloading them into imagebuffers, adding them to an object that implements the Java Printable interface, creating a printer job, displaying a printer dialog window, and then calling the printer job print function.
[code]#place this code in a module named app.printing
from java.awt.print import Printable
class MultiPageDoc(Printable):
def init(self):
self.__mDoc = []
def append(self, image):
self.__mDoc.append(image)
def print(self, graphics, pageFormat, pageIndex):
from java.awt.print import Printable
from java.awt.print import PageFormat
from java.awt import AlphaComposite
from java.awt import RenderingHints
if pageIndex < len(self.__mDoc):
image = self.__mDoc[pageIndex]
xScale = pageFormat.getImageableWidth() / image.getWidth()
yScale = pageFormat.getImageableHeight() / image.getHeight()
scale = min(xScale, yScale)
if xScale < yScale:
#width dictates scale, center vertically
graphics.translate(pageFormat.getImageableY(), pageFormat.getImageableY() + (pageFormat.getImageableHeight() - (scale * image.getHeight())) / 2.0)
else:
#height dictates scale, center horizontally
graphics.translate(pageFormat.getImageableY() + (pageFormat.getImageableWidth() - (scale * image.getWidth())) / 2.0, pageFormat.getImageableY())
graphics.scale(scale, scale)
graphics.setComposite(AlphaComposite.Src)
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
graphics.drawImage(image, 0, 0, None)
return Printable.PAGE_EXISTS;
else:
return Printable.NO_SUCH_PAGE
def printMultiPageDoc(mDoc):
from fpmi.gui import messageBox, errorBox
from java.awt.print import PrinterJob
from javax.print import DocFlavor, PrintServiceLookup
from javax.print.attribute import HashPrintRequestAttributeSet
from javax.print.attribute.standard import OrientationRequested, JobName, Chromaticity
#create a print job and assign the multi-page document as the printable object
printJob = PrinterJob.getPrinterJob()
printJob.setPrintable(mDoc)
#specify a 'Printable' document flavor
docFlavor = DocFlavor('application/x-java-jvm-local-objectref', 'java.awt.print.Printable')
#set desired attributes for a print service (i.e., printer)
attributeSet = HashPrintRequestAttributeSet()
attributeSet.add(OrientationRequested.LANDSCAPE)
attributeSet.add(Chromaticity.COLOR) #print in color
attributeSet.add(JobName("FPMI Multi-page Document", None)) #assign print job name
#locate a print service that will handle the desired document flavor and attributes
services = PrintServiceLookup.lookupPrintServices(docFlavor, attributeSet)
if len(services) > 0:
#show a print dialog window so user can select the printer, set margins, set page orientation, etc.
if printJob.printDialog(attributeSet):
try:
printJob.print(attributeSet)
messageBox('Printing complete.')
except:
errorBox('An unexpected error was encountered while printing the multi-page document.')
else:
messageBox('Printing cancelled.')
else:
errorBox('No printer with the necessary attributes and capable of handling a "Printable" document was found.')
[/code]I wanted to have more control when creating a temporary file so I created my own routine to get one.
[code]#place this code in a module named app.misc
def getTempFilename():
from java.lang.System import getenv, getProperty
from java.io import File
from os.path import join
from random import random
tmpPath = getenv('tmp')
if tmpPath == None:
tmpPath = getenv('temp')
if tmpPath == None:
tmpPath = getProperty("user.home")
tempFilename = join(tmpPath, ("fpmi%09d.jpg" % (999999999 * random())))
tempFile = File(tempFilename)
while tempFile.exists():
tempFilename = join(tmpPath, ("fpmi%09d.jpg" % (999999999 * random())))
tempFile = File(tempFilename)
tempFile = None
return tempFilename
[/code]
The following code is responsible for printing the charts to an image file, reloading them into an bufferimage, and adding the bufferimages to my MultiPageDoc:
[code]#place this code in a module named app.testing
def testPrintCharts():
from app.printing import MultiPageDoc, printMultiPageDoc
from app.misc import getTempFilename
from fpmi.gui import getWindow
from fpmi.print import printToImage
from java.awt.image import BufferedImage
from java.io import File
from javax.imageio import ImageIO
from os import unlink
chart = getWindow('Floating').rootContainer.getComponent('ChartContainer')
mDoc = MultiPageDoc()
for index in range(0, 2):
#write window image to a random file, read it back into a buffered image,
#then append the buffered image to the multi-page document
filename = getTempFilename()
printToImage(chart, filename)
file = File(filename);
bufferedImage = ImageIO.read(file)
unlink(filename)
mDoc.append(bufferedImage)
printMultiPageDoc(mDoc)
[/code]In my test application I have one window name ‘Floating’. I open it and execute the following code in the script playground to print two copies of a single chart from the ‘Floating’ window:
import app.testing
app.testing.testPrintCharts()