使用Java打印API打印多页(可能是打印机或PDF)文档时出现错误迭代

使用Java打印API打印多页(可能是打印机或PDF)文档时出现错误迭代,java,swing,awt,printers,java-print,Java,Swing,Awt,Printers,Java Print,我正在使用Java打印API,并从oracle页面获得了打印账单发票的多页文档的代码 和本页的示例代码 现在,正如您所知,大多数发票都有项目的账单明细,从页面的中心顶部开始,这是动态值,有时明细会被推到下一页 我摆弄和修改上面的代码,下面是我的工作代码 import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.print.*; public class PaginationExampl

我正在使用Java打印API,并从oracle页面获得了打印账单发票的多页文档的代码

和本页的示例代码

现在,正如您所知,大多数发票都有项目的账单明细,从页面的中心顶部开始,这是动态值,有时明细会被推到下一页

我摆弄和修改上面的代码,下面是我的工作代码

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);
    }
}


import java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
导入java.awt.print.*;
公共类PaginationExample实现了可打印的ActionListener{
int[]pageBreaks1,pageBreaks2;//分页符行位置数组。
/*合成一些文本样本行*/
字符串[][]文本行;
私有void initTextLines(){
if(textLines==null){
int numLines=300;
textLines=新字符串[numLines][3];
textLines=新字符串[numLines][4];

对于(int i=0;i我更改了
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; // 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.awt.BorderLayout;
导入java.awt.Font;
导入java.awt.FontMetrics;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.geom.Rectangle2D;
导入java.awt.print.PageFormat;
导入java.awt.print.Printable;
导入java.awt.print.PrinterException;
导入java.awt.print.PrinterJob;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.SwingUtilities;
公共类PaginationExample实现了可打印的ActionListener{
int[]pageBreaks1,pageBreaks2;//分页符行位置数组。
/*合成一些文本样本行*/
字符串[][]文本行;
公共分页示例(){
initTextLines();
}
私有void initTextLines(){
int numLines=300;
textLines=新字符串[numLines][4];
对于(int i=0;i0){
start+=linesPerPage1+linesPerPage2*(页面索引-1);
结束=开始+行sperpage2;
}
end=Math.min(end,textLines.length);
对于(int line=start;line如果(开始)它就行了!谢谢!如果可能的话,我可以得到更多关于你更改代码的解释吗?对不起,请解释一下,我重新阅读了你的答案,非常清楚。再次表示衷心的感谢!。
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);
            }
        });
    }
}