使用 Java 打印 API 打印多页(可能是打印机或 PDF)文档时出现错误迭代
Wrong iteration while printing a multiple page(Possibly printer or PDF) document using Java Printing API
我正在使用 Java 打印 API 并从这个 oracle 页面获得了打印多页发票文档的代码。
Printing a Multiple Page Document
以及此页面中的示例代码
如您所知,现在大多数发票都有从页面中心顶部开始的项目账单详细信息,这是动态值,有时详细信息会被推送到下一页。
我 fiddle 并使用上面的代码进行修改,下面是我的工作代码。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks1, pageBreaks2; // array of page break line positions.
/* Synthesize some sample lines of text */
String[][] textLines;
private void initTextLines() {
if (textLines == null) {
int numLines=300;
textLines = new String[numLines][3];
textLines = new String[numLines][4];
for (int i=0;i<numLines;i++) {
textLines[i][0]= "1. This is line number " + i;
textLines[i][1]= "2. This is line number " + i;
textLines[i][2]= "3. This is line number " + i;
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
int linesPerPage1 = (int)(550/lineHeight);
int linesPerPage2 = (int)(750/lineHeight);
initTextLines();
if (pageBreaks1 == null) {
int numBreaks1 = (textLines.length-1)/linesPerPage1;
pageBreaks1 = new int[numBreaks1];
for (int b1=0; b1<numBreaks1; b1++) {
pageBreaks1[b1] = (b1+1)*linesPerPage1;
}
}
if (pageBreaks2 == null) {
int numBreaks2 = (textLines.length-1)/linesPerPage2;
pageBreaks2 = new int[numBreaks2];
for (int b2=0; b2<numBreaks2; b2++) {
pageBreaks2[b2] = (b2+1)*linesPerPage2;
}
}
if (pageIndex > pageBreaks1.length) {
return NO_SUCH_PAGE;
}
if (pageIndex > pageBreaks2.length) {
return NO_SUCH_PAGE;
}
/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = (pageIndex == 0) ? 200 : 30;
int start = (pageIndex == 0) ? ((pageIndex == 0) ? 0 : pageBreaks1[pageIndex-1])
: ((pageIndex == 0) ? 0 : pageBreaks2[pageIndex-1]);
int end = (pageIndex == 0) ? ((pageIndex == pageBreaks1.length) ? textLines.length : pageBreaks1[pageIndex])
: ((pageIndex == pageBreaks2.length) ? textLines.length : pageBreaks2[pageIndex]);
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line][0], 10, y);
g.drawString(textLines[line][1], 100, y);
g.drawString(textLines[line][2], 200, y);
g.drawString(textLines[line][3], 300, y);
}
return PAGE_EXISTS;
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
public static void main(String args[]) {
try {
String cn = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(cn); // Use the native L&F
} catch (Exception cnf) {
}
JFrame f = new JFrame("Printing Pagination Example");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add("Center", printButton);
f.pack();
f.setVisible(true);
}
}
现在我得到的问题是下图中的这个。
pdf output image
发生的事情是代码在迭代中出错,因为数组中的某些元素跳转了,这个错误只发生在第一页。
我相信上面发布的代码中的问题出在这里。
int y = (pageIndex == 0) ? 200 : 30;
int start = (pageIndex == 0) ? ((pageIndex == 0) ? 0 : pageBreaks1[pageIndex-1])
: ((pageIndex == 0) ? 0 : pageBreaks2[pageIndex-1]);
int end = (pageIndex == 0) ? ((pageIndex == pageBreaks1.length) ? textLines.length : pageBreaks1[pageIndex])
: ((pageIndex == pageBreaks2.length) ? textLines.length : pageBreaks2[pageIndex]);
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line][0], 10, y);
g.drawString(textLines[line][1], 100, y);
g.drawString(textLines[line][2], 200, y);
g.drawString(textLines[line][3], 300, y);
}
它尝试修复迭代,但它不起作用。如果可能的话,请指导我哪里出错了。
谢谢 :).
我对您的 print
方法进行了更改,以大大简化开始和结束文本行的计算。
我做了一些其他更改,主要是一次性生成文本行并 space 水平输出这些行。
这是修改后的包含的可执行代码。我希望我可以 post pdf 打印输出,但您必须 运行 代码才能看到结果。
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks1, pageBreaks2; // array of page break line positions.
/* Synthesize some sample lines of text */
String[][] textLines;
public PaginationExample() {
initTextLines();
}
private void initTextLines() {
int numLines = 300;
textLines = new String[numLines][4];
for (int i = 0; i < numLines; i++) {
textLines[i][0] = "1. This is line number " + i;
textLines[i][1] = "2. This is line number " + i;
textLines[i][2] = "3. This is line number " + i;
textLines[i][3] = "4. This is line number " + i;
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
int linesPerPage1 = (int) (550 / lineHeight);
int linesPerPage2 = (int) (750 / lineHeight);
/*
* User (0,0) is typically outside the imageable area, so we must translate by
* the X and Y values in the PageFormat to avoid clipping Since we are drawing
* text we
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/*
* Draw each line that is on this page. Increment 'y' position by lineHeight for
* each line.
*/
int y = (pageIndex == 0) ? 200 : 30;
int start = 0;
int end = linesPerPage1;
if (pageIndex > 0) {
start += linesPerPage1 + linesPerPage2 * (pageIndex - 1);
end = start + linesPerPage2;
}
end = Math.min(end, textLines.length);
for (int line = start; line < end; line++) {
y += lineHeight;
Rectangle2D r2d = metrics.getStringBounds(textLines[line][0], g2d);
g.drawString(textLines[line][0], 10, y);
int width = 50 + (int) r2d.getWidth();
g.drawString(textLines[line][1], width, y);
r2d = metrics.getStringBounds(textLines[line][1], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[line][2], width, y);
r2d = metrics.getStringBounds(textLines[line][2], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[line][3], width, y);
}
if (start <= textLines.length) {
return PAGE_EXISTS;
} else {
return NO_SUCH_PAGE;
}
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("Printing Pagination Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add(printButton, BorderLayout.CENTER);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
我正在使用 Java 打印 API 并从这个 oracle 页面获得了打印多页发票文档的代码。
Printing a Multiple Page Document
以及此页面中的示例代码
如您所知,现在大多数发票都有从页面中心顶部开始的项目账单详细信息,这是动态值,有时详细信息会被推送到下一页。
我 fiddle 并使用上面的代码进行修改,下面是我的工作代码。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks1, pageBreaks2; // array of page break line positions.
/* Synthesize some sample lines of text */
String[][] textLines;
private void initTextLines() {
if (textLines == null) {
int numLines=300;
textLines = new String[numLines][3];
textLines = new String[numLines][4];
for (int i=0;i<numLines;i++) {
textLines[i][0]= "1. This is line number " + i;
textLines[i][1]= "2. This is line number " + i;
textLines[i][2]= "3. This is line number " + i;
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
int linesPerPage1 = (int)(550/lineHeight);
int linesPerPage2 = (int)(750/lineHeight);
initTextLines();
if (pageBreaks1 == null) {
int numBreaks1 = (textLines.length-1)/linesPerPage1;
pageBreaks1 = new int[numBreaks1];
for (int b1=0; b1<numBreaks1; b1++) {
pageBreaks1[b1] = (b1+1)*linesPerPage1;
}
}
if (pageBreaks2 == null) {
int numBreaks2 = (textLines.length-1)/linesPerPage2;
pageBreaks2 = new int[numBreaks2];
for (int b2=0; b2<numBreaks2; b2++) {
pageBreaks2[b2] = (b2+1)*linesPerPage2;
}
}
if (pageIndex > pageBreaks1.length) {
return NO_SUCH_PAGE;
}
if (pageIndex > pageBreaks2.length) {
return NO_SUCH_PAGE;
}
/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = (pageIndex == 0) ? 200 : 30;
int start = (pageIndex == 0) ? ((pageIndex == 0) ? 0 : pageBreaks1[pageIndex-1])
: ((pageIndex == 0) ? 0 : pageBreaks2[pageIndex-1]);
int end = (pageIndex == 0) ? ((pageIndex == pageBreaks1.length) ? textLines.length : pageBreaks1[pageIndex])
: ((pageIndex == pageBreaks2.length) ? textLines.length : pageBreaks2[pageIndex]);
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line][0], 10, y);
g.drawString(textLines[line][1], 100, y);
g.drawString(textLines[line][2], 200, y);
g.drawString(textLines[line][3], 300, y);
}
return PAGE_EXISTS;
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
public static void main(String args[]) {
try {
String cn = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(cn); // Use the native L&F
} catch (Exception cnf) {
}
JFrame f = new JFrame("Printing Pagination Example");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add("Center", printButton);
f.pack();
f.setVisible(true);
}
}
现在我得到的问题是下图中的这个。
pdf output image
发生的事情是代码在迭代中出错,因为数组中的某些元素跳转了,这个错误只发生在第一页。
我相信上面发布的代码中的问题出在这里。
int y = (pageIndex == 0) ? 200 : 30;
int start = (pageIndex == 0) ? ((pageIndex == 0) ? 0 : pageBreaks1[pageIndex-1])
: ((pageIndex == 0) ? 0 : pageBreaks2[pageIndex-1]);
int end = (pageIndex == 0) ? ((pageIndex == pageBreaks1.length) ? textLines.length : pageBreaks1[pageIndex])
: ((pageIndex == pageBreaks2.length) ? textLines.length : pageBreaks2[pageIndex]);
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line][0], 10, y);
g.drawString(textLines[line][1], 100, y);
g.drawString(textLines[line][2], 200, y);
g.drawString(textLines[line][3], 300, y);
}
它尝试修复迭代,但它不起作用。如果可能的话,请指导我哪里出错了。
谢谢 :).
我对您的 print
方法进行了更改,以大大简化开始和结束文本行的计算。
我做了一些其他更改,主要是一次性生成文本行并 space 水平输出这些行。
这是修改后的包含的可执行代码。我希望我可以 post pdf 打印输出,但您必须 运行 代码才能看到结果。
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks1, pageBreaks2; // array of page break line positions.
/* Synthesize some sample lines of text */
String[][] textLines;
public PaginationExample() {
initTextLines();
}
private void initTextLines() {
int numLines = 300;
textLines = new String[numLines][4];
for (int i = 0; i < numLines; i++) {
textLines[i][0] = "1. This is line number " + i;
textLines[i][1] = "2. This is line number " + i;
textLines[i][2] = "3. This is line number " + i;
textLines[i][3] = "4. This is line number " + i;
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
int linesPerPage1 = (int) (550 / lineHeight);
int linesPerPage2 = (int) (750 / lineHeight);
/*
* User (0,0) is typically outside the imageable area, so we must translate by
* the X and Y values in the PageFormat to avoid clipping Since we are drawing
* text we
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/*
* Draw each line that is on this page. Increment 'y' position by lineHeight for
* each line.
*/
int y = (pageIndex == 0) ? 200 : 30;
int start = 0;
int end = linesPerPage1;
if (pageIndex > 0) {
start += linesPerPage1 + linesPerPage2 * (pageIndex - 1);
end = start + linesPerPage2;
}
end = Math.min(end, textLines.length);
for (int line = start; line < end; line++) {
y += lineHeight;
Rectangle2D r2d = metrics.getStringBounds(textLines[line][0], g2d);
g.drawString(textLines[line][0], 10, y);
int width = 50 + (int) r2d.getWidth();
g.drawString(textLines[line][1], width, y);
r2d = metrics.getStringBounds(textLines[line][1], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[line][2], width, y);
r2d = metrics.getStringBounds(textLines[line][2], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[line][3], width, y);
}
if (start <= textLines.length) {
return PAGE_EXISTS;
} else {
return NO_SUCH_PAGE;
}
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("Printing Pagination Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add(printButton, BorderLayout.CENTER);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}