英文:
Wrong iteration while printing a multiple page(Possibly printer or PDF) document using Java Printing API
问题
我正在使用Java打印API,并从这个Oracle页面获取了打印多页账单发票的代码。
这个页面的示例代码如下:
现在,你知道大多数发票的计费明细从页面的中上部开始,这些是动态值,有时明细会被推到下一页。
我对上述代码进行了一些修改,并且以下是我的工作代码。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
public class PaginationExample implements Printable, ActionListener {
// 其他部分保持不变...
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
// 其他部分保持不变...
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 static void main(String args[]) {
// 其他部分保持不变...
}
}
现在,我遇到的问题是下面图片中所示的问题。
问题在于代码在迭代过程中出错,导致跳过了数组中的某些元素,而这个错误只发生在第一页中。
我相信我上面发布的代码中的问题出在这里。
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);
}
我尝试过修复迭代,但它不起作用。如果可能的话,请指导我在哪里出错了。
谢谢 :).
英文:
I am using Java Printing API and have got the code of printing multiple page document of billing invoice from this oracle page.
Printing a Multiple Page Document
And Example code from this page
Now as you know most invoice have billing details of items start from center-top of the page which is dynamic values sometimes details get pushed to next page.
I fiddle and modify with above code and below is my working code.
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[0], 10, y);
g.drawString(textLines[1], 100, y);
g.drawString(textLines[2], 200, y);
g.drawString(textLines[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);
}
}
Now the issue I get is this in below picture.
What is happening is code is taking the iteration wrong because of and jumping some elements in the array and this error is only happening in first page.
I do believe my problem in the above posted code lies here.
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[0], 10, y);
g.drawString(textLines[1], 100, y);
g.drawString(textLines[2], 200, y);
g.drawString(textLines[3], 300, y);
}
It tried fixing the iteration but it doesn't work. Please if possible guide me where I am going wrong here.
Thank you :).
答案1
得分: 1
我对你的print
方法进行了修改,大大简化了起始和结束文本行的计算。
我还做了一些其他的改变,主要是一次生成文本行,并在水平方向上进行了调整。
以下是修订后的、完整的可执行代码。我希望我能够展示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; // 分页线位置的数组。
/* 合成一些示例文本行 */
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. 这是第 " + i + " 行";
textLines[i][1] = "2. 这是第 " + i + " 行";
textLines[i][2] = "3. 这是第 " + i + " 行";
textLines[i][3] = "4. 这是第 " + 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);
/*
* 用户 (0,0) 通常在图像区域之外,所以我们必须根据 PageFormat 中的 X 和 Y 值进行平移,以避免剪切
* 因为我们要绘制文本,所以我们...
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/*
* 绘制在此页上的每一行。对于每一行,通过 lineHeight 增加 y 位置。
*/
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("打印分页示例");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton printButton = new JButton("打印页面");
printButton.addActionListener(new PaginationExample());
f.add(printButton, BorderLayout.CENTER);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
英文:
I made changes to your print
method to greatly simplify the calculation of the start and end text line.
I made some other changes, mainly to generate the text lines one time and to space out the lines horizontally.
Here's the revised, contained, executable code. I wish I could post the pdf print output, but you'll have to run the code to see the results.
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[0], g2d);
g.drawString(textLines[0], 10, y);
int width = 50 + (int) r2d.getWidth();
g.drawString(textLines[1], width, y);
r2d = metrics.getStringBounds(textLines[1], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[2], width, y);
r2d = metrics.getStringBounds(textLines[2], g2d);
width += 40 + (int) r2d.getWidth();
g.drawString(textLines[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);
}
});
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论