Почему этот код Java Page Printing чрезвычайно медленный и есть ли альтернатива ему?
Я использую интерфейс для печати. Точный код для PrintPanel, который реализует Printable:
package accessory;
// all necessary imports
public class PrintPanel implements Printable {
BufferedImage printableImages[] = null;
DynPanel printable = null;
public Font printFont = new Font("Arial", Font.BOLD , 10);
public String headerStr = null , footerStr = null;
public boolean draw_pageBorder = false;
public Color borderColor = Color.BLACK;
public int pageBorder_thickness = 2;
public int pageCount = 1;
public PrintPanel(DynPanel panel)
{
printable = panel;
pageCount = 1;
}
public PrintPanel(BufferedImage images[])
{
printableImages = images;
pageCount = images.length;
}
@Override
public int print(Graphics g, PageFormat pageFormat, int page) throws PrinterException
{
System.out.println("entered print command");
if(page < pageCount )
{
//--- Create the Graphics2D object
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(), pageFormat
.getImageableY());
//--- Translate the origin to 0,0 for the top left corner
int fontHeight = g2d.getFontMetrics().getHeight();
int fontDescent = g2d.getFontMetrics().getDescent();
int lineHeight = fontHeight+ fontDescent;
int fontWidth_header = g2d.getFontMetrics().stringWidth(headerStr);
int fontWidth_footer = g2d.getFontMetrics().stringWidth(footerStr);
int remainder_header = (int)Math.ceil( pageFormat.getImageableWidth() ) - fontWidth_header;
remainder_header /= 2d;
int remainder_footer = (int)Math.ceil( pageFormat.getImageableWidth() ) - fontWidth_footer;
remainder_footer /= 2d;
if(draw_pageBorder)
{
g2d.setPaint(borderColor);
g2d.setStroke(new BasicStroke(pageBorder_thickness));
Rectangle2D.Double border = new Rectangle2D.Double(0, 0, pageFormat
.getImageableWidth()+4, pageFormat.getImageableHeight()+4);
g2d.draw(border);
}
g2d.setFont(printFont);
// code for printing DynPanel (JPanel)
if(printable != null)
{
Dimension compSize = printable.getPreferredSize();
// Make sure we size to the preferred size
printable.setSize(compSize);
// Get the the print size
Dimension printSize = new Dimension();
printSize.setSize(pageFormat.getImageableWidth(), pageFormat.getImageableHeight());
// Calculate the scale factor
double scaleFactor = getScaleFactorToFit(compSize, printSize);
// Don't want to scale up, only want to scale down
if (scaleFactor > 1d) {
scaleFactor = 1d;
}
// Calculate the scaled size...
double scaleWidth = compSize.width * scaleFactor;
double scaleHeight = compSize.height * scaleFactor;
// Create a clone of the graphics context. This allows us to manipulate
// the graphics context without begin worried about what effects
// it might have once we're finished
//Graphics2D g2d = (Graphics2D) g.create();
// Calculate the x/y position of the component, this will center
// the result on the page if it can
double x = ((pageFormat.getImageableWidth() - scaleWidth) / 2d) + pageFormat.getImageableX();
double y = ((pageFormat.getImageableHeight() - scaleHeight) / 2d) + pageFormat.getImageableY();
AffineTransform at = new AffineTransform();
// Translate the offset to out "center" of page
at.translate(x, y);
// Set the scaling
at.scale(scaleFactor, scaleFactor);
// Apply the transformation
g2d.transform(at);
// Print the component
printable.printAll(g2d);
}
else // code for printing BufferedImages 'printableImages'
{
try{
int width = (int) pageFormat.getImageableWidth();
int height = (int) pageFormat.getImageableHeight();
int imageWidth = printableImages[page].getWidth();
int imageHeight = printableImages[page].getHeight();
double scaleX = (double)width/imageWidth;
double scaleY = (double)height/imageHeight;
AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY);
AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR);
printableImages[page] = bilinearScaleOp.filter(
printableImages[page],
new BufferedImage(width, height, printableImages[page].getType()));
System.out.println("Printing IMAGE="+printableImages[page]);
g2d.drawImage(printableImages[page] , (int)pageFormat.getImageableX() , ( (int)pageFormat.getImageableY() + (8 + lineHeight) ), null);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("ERROR IN PRINTING IMAGE");
e.printStackTrace();
}
}
if(headerStr != null)
g2d.drawString( headerStr , (int)pageFormat.getImageableX() + remainder_header , (int)pageFormat.getImageableY() + (8 + lineHeight));
if(footerStr != null)
{
if(footerStr.equals("print_page_index"))
g2d.drawString( ("Page "+( page + 1) + " of " + pageCount ) , (int)pageFormat.getImageableX() + remainder_footer , (int)pageFormat.getImageableY() + ((int)pageFormat.getImageableHeight() - lineHeight - 8 ));
else
g2d.drawString( footerStr , (int)pageFormat.getImageableX() + remainder_footer , (int)pageFormat.getImageableY() + ((int)pageFormat.getImageableHeight() - lineHeight - 8));
}
//else System.out.println("EMPTY PRINT");
//g2d.dispose();
if(printable != null) printable.revalidate();
// printable.paint(g2d);
return Printable.PAGE_EXISTS;
}
else return Printable.NO_SUCH_PAGE;
}
}
Я использую конструктор PrintPanel(BufferedImage images[])
Теперь я вызываю функцию printDocument(), которая имеет следующий код:
private void printDocument() { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("Initiating print command.."); long t1 = System.currentTimeMillis(); PrinterJob printJob = PrinterJob.getPrinterJob(); Book book = new Book(); PageFormat documentPageFormat = new PageFormat(); documentPageFormat.setOrientation(PageFormat.PORTRAIT); BufferedImage pages[] = new BufferedImage[pane.pageCount]; for(int count = 0; count < pane.pageCount; count ++ ) pages[count] = pane.pages[count].getSnapshot(); PrintPanel printImage = new PrintPanel(pages); printImage.headerStr = "Java Study Frame : " + ( docName != null ? (( docName.replaceAll("\\s+" , "").isEmpty() ? " Untitled JSF Document " : docName ) ) : " Untitled JSF Document " ) ; printImage.footerStr = "print_page_index"; printJob.setJobName("Java Study Frame Print"); long t2 = System.currentTimeMillis(); System.out.println("Setting printable. Prev time = " + (t2 - t1)/1000 +" seconds!"); t1 = System.currentTimeMillis(); printJob.setPrintable(printImage); t2 = System.currentTimeMillis(); System.out.println("Printable set in " + (t2 - t1)/1000 + " seconds !"); if (printJob.printDialog()) { try { printJob.print(); } catch (Exception PrintException) { PrintException.printStackTrace(); } } } });
}
Мои вопросы
- Буквально каждый раз требуетсяболее 30 секунд для того, чтобы диалоговое окно печати появилось после того, как "инициирующая команда печати" была напечатана на консоли. Что вызывает это?
- Даже после нажатия кнопки "Печать" в диалоговом окне печати на создание задания печати уходит не менее 40-50 секунд. Это почему? (Я печатаю максимум 1 - 2 страницы)
Для выхода за пределы setPrintable() требуется, как правило, 3–6 секунд (предыдущее время = 0 секунд, а для набора для печати = 3–6 секунд), что означает, что оператор printJob.printDialog() занимает время. Что может быть причиной?
Как свидетельствуют другие вопросы, печать на Java кажется медленной. Если да, есть ли какой-нибудь другой API для печати страниц в Java, который я мог бы использовать?
- Даже когда я добавил только один printableImage, функция print(), кажется, вызывается несколько раз ( 2-3 раза), о чем свидетельствует "введенная команда печати" на консоли. Это правильно?
- Несмотря на то, что весь printDocument() запускается в отдельном потоке, он ЗАЯВЛЯЕТ МОЕ ПРИЛОЖЕНИЕ. Как это может случиться. Что я здесь не так делаю?