如何使用Java和itext从图形对象创建包含多个页面的PDF
我有一个抽象类,它有一个抽象方法draw(Graphics2D g2),还有一些方法print()、showPreview()、printPDF()。对于Java程序中的每个文档,我都实现draw(),这样我就可以打印、显示预览并为每个文档创建一个PDF文件。 我的问题是如何从该图形对象创建包含多个页面的PDF。 我通过为每个页面创建一个PDF文件来解决这个问题,然后将这些文件合并到一个新文件中。但一定有更好的办法。 我有以下代码创建一页PDF:如何使用Java和itext从图形对象创建包含多个页面的PDF,java,pdf,itext,Java,Pdf,Itext,我有一个抽象类,它有一个抽象方法draw(Graphics2D g2),还有一些方法print()、showPreview()、printPDF()。对于Java程序中的每个文档,我都实现draw(),这样我就可以打印、显示预览并为每个文档创建一个PDF文件。 我的问题是如何从该图形对象创建包含多个页面的PDF。 我通过为每个页面创建一个PDF文件来解决这个问题,然后将这些文件合并到一个新文件中。但一定有更好的办法。 我有以下代码创建一页PDF: public void printPDF1(){
public void printPDF1(){
JFileChooser dialog = new JFileChooser();
String filePath = "";
int dialogResult = dialog.showSaveDialog(null);
if (dialogResult==JFileChooser.APPROVE_OPTION){
filePath = dialog.getSelectedFile().getPath();
}
else return;
try {
Document document = new Document(new Rectangle(_pageWidth, _pageHeight));
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(filePath));
document.open();
PdfContentByte cb = writer.getDirectContent();
g2 = cb.createGraphics(_pageWidth, _height);
g2.translate(0, (_numberOfPages - _pageNumber) * _pageHeight);
draw(g2);
g2.dispose();
document.close();
}
catch (Exception e2) {
System.out.println(e2.getMessage());
}
}
document.open();
//返回相同的contentByte,它只是在
//新页面事件。
PdfContentByte cb=writer.getDirectContent();
对于(int_pageNumber=0;_pageNumber<\u numberofPages;+\u numberofPages){
/*******************/
//第一关无害,第二关必需
document.newPage();
/*******************/
g2=cb.createGraphics(_页面宽度,_高度);
g2.翻译(0,(\u页码-\u页码)*\u页高);
绘制(g2);
g2.dispose();
}
document.close();
因此,您要渲染整个界面N次,并且只在不同的位置显示页面大小的部分。这在印刷世界IIRC中被称为“条纹”。很聪明,但在PDF中可能会更有效
一次将整个界面渲染为一个巨大的PdfTemplate(使用g2d)。然后将该模板绘制到所有页面中,以便在当前页面的页边距(“媒体框”)中可以看到所需的部分
PdfContentByte cb=writer.getDirectContent();
float entireHeight=_numberOfPages*_pageHeight;
PdfTemplate hugeTempl=cb.createTemplate(0,-entireHeight,pageWidth,_pageHeight);
g2=hugeTempl.createGraphics(0,-全高,_页面宽度,_页面高度);
绘制(g2);
g2.dispose();
对于(int curPg=0;curPg<_numberOfPages;++curPg){
cb.addTemplateSimple(hugeTempl,0,--u页面高度*curPg);
document.newPage();
}
PDF的坐标空间在左下角设置为0,0,这些值随着向上和向右移动而增加。PdfGraphis2D做了相当多的魔术来隐藏这种差异,但我们仍然需要在这里处理一点。。。因此,边界框和图形位置中的负坐标
这都是“餐巾纸背面”的编码,我完全有可能犯了一两个错误。。。但这就是我的想法。我在遵循上面的代码时遇到了问题(在当前的itextpdf版本中,某些方法似乎已经更改)。以下是我的解决方案:
import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.WindowEvent;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class PanelToPDF {
private static JFrame frame= new JFrame();
private static JPanel view= new JPanel();
private static float pageWidth= PageSize.A4.getWidth();
private static float pageHeight= PageSize.A4.getHeight();
public static void main(String[] args) throws Exception {
System.out.println("Page width = " + pageWidth + ", height = " + pageHeight);
initPane();
createMultipagePDF();
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
private static void initPane() {
view.setLayout(new MigLayout());
view.setBackground(Color.WHITE);
for (int i= 1; i <= 160; ++i) {
JLabel label= new JLabel("This is a test! " + i);
label.setForeground(Color.BLACK);
view.add(label, "wrap");
JPanel subPanel= new JPanel();
subPanel.setBackground(Color.RED);
view.add(subPanel);
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(Math.round(pageWidth), Math.round(pageHeight)));
frame.add(view);
frame.setVisible(true);
}
private static void createMultipagePDF() throws Exception {
// Calculate the number of pages required. Use the preferred size to get
// the entire panel height, rather than the panel height within the JFrame
int numPages= (int) Math.ceil(view.getPreferredSize().height / pageHeight); // int divided by float
// Output to PDF
OutputStream os= new FileOutputStream("test.pdf");
Document doc= new Document();
PdfWriter writer= PdfWriter.getInstance(doc, os);
doc.open();
PdfContentByte cb= writer.getDirectContent();
// Iterate over pages here
for (int currentPage= 0; currentPage < numPages; ++currentPage) {
doc.newPage(); // not needed for page 1, needed for >1
PdfTemplate template= cb.createTemplate(pageWidth, pageHeight);
Graphics2D g2d= new PdfGraphics2D(template, pageWidth, pageHeight * (currentPage + 1));
view.printAll(g2d);
g2d.dispose();
cb.addTemplate(template, 0, 0);
}
doc.close();
}
import com.itextpdf.awt.PdfGraphics2D;
导入com.itextpdf.text.Document;
导入com.itextpdf.text.PageSize;
导入com.itextpdf.text.pdf.PdfContentByte;
导入com.itextpdf.text.pdf.PdfTemplate;
导入com.itextpdf.text.pdf.PdfWriter;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics2D;
导入java.awt.event.WindowEvent;
导入java.io.FileOutputStream;
导入java.io.OutputStream;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入net.miginfocom.swing.MigLayout;
公共类PanelToPDF{
私有静态JFrame=新JFrame();
私有静态JPanel视图=新JPanel();
私有静态浮点pageWidth=PageSize.A4.getWidth();
private static float pageHeight=PageSize.A4.getHeight();
公共静态void main(字符串[]args)引发异常{
System.out.println(“页面宽度=“+pageWidth+”,高度=“+pageHeight”);
initPane();
createMultipagePDF();
frame.dispatchEvent(新的WindowEvent(frame,WindowEvent.WINDOW_关闭));
}
私有静态void initPane(){
view.setLayout(新的MigLayout());
视图.背景(颜色.白色);
对于(int i=1;i 1
PdfTemplate template=cb.createTemplate(页面宽度、页面高度);
Graphics2D g2d=新的PdfGraphics2D(模板、页面宽度、页面高度*(当前页面+1));
view.printAll(g2d);
g2d.dispose();
cb.addTemplate(模板,0,0);
}
doc.close();
}
哪些改变?PS:这是你点击正确答案旁边空洞的复选标记的部分,让其他人知道谁是对的(并给那个人一些声誉)。“我”在这种情况下。另外,如果你问了多个问题,却从来没有给他们打分,其他人会看到你的回答率很低,也不太可能麻烦,因为他们知道即使他们是对的,你也不会给他们打分。对不起,马克,我试图了解这个网站是如何工作的。我没有意识到PdfContentByte可以在每个pa中重复使用我做了如下更改:PdfTemplate template=cb.createTemplate(_pageWidth,entireHeight);g2=template.createGraphics(_pageWidth,entireHeight);…for(int curPg=1;curPg不用担心。我会用粉笔记录你的“注释中的代码”更多相同的内容。欢迎来到SO。无知是可以治愈的,但愚蠢是永远的。
总是乐于治愈一些无知。@MarkStorer我使用的是您在回答中提供的第二个代码片段。不知何故,我得到的只是最后一页的内容。有什么解决方案吗?您只是一遍又一遍地看到最后一页,或者只看到最后一页网页有内容吗?
PdfContentByte cb = writer.getDirectContent();
float entireHeight = _numberOfPages * _pageHeight;
PdfTemplate hugeTempl = cb.createTemplate( 0, -entireHeight, pageWidth, _pageHeight );
g2 = hugeTempl.createGraphics(0, -entireHeight, _pageWidth, _pageHeight );
draw(g2);
g2.dispose();
for (int curPg = 0; curPg < _numberOfPages; ++curPg) {
cb.addTemplateSimple( hugeTempl, 0, -_pageHeight * curPg );
document.newPage();
}
import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.WindowEvent;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class PanelToPDF {
private static JFrame frame= new JFrame();
private static JPanel view= new JPanel();
private static float pageWidth= PageSize.A4.getWidth();
private static float pageHeight= PageSize.A4.getHeight();
public static void main(String[] args) throws Exception {
System.out.println("Page width = " + pageWidth + ", height = " + pageHeight);
initPane();
createMultipagePDF();
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
private static void initPane() {
view.setLayout(new MigLayout());
view.setBackground(Color.WHITE);
for (int i= 1; i <= 160; ++i) {
JLabel label= new JLabel("This is a test! " + i);
label.setForeground(Color.BLACK);
view.add(label, "wrap");
JPanel subPanel= new JPanel();
subPanel.setBackground(Color.RED);
view.add(subPanel);
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(Math.round(pageWidth), Math.round(pageHeight)));
frame.add(view);
frame.setVisible(true);
}
private static void createMultipagePDF() throws Exception {
// Calculate the number of pages required. Use the preferred size to get
// the entire panel height, rather than the panel height within the JFrame
int numPages= (int) Math.ceil(view.getPreferredSize().height / pageHeight); // int divided by float
// Output to PDF
OutputStream os= new FileOutputStream("test.pdf");
Document doc= new Document();
PdfWriter writer= PdfWriter.getInstance(doc, os);
doc.open();
PdfContentByte cb= writer.getDirectContent();
// Iterate over pages here
for (int currentPage= 0; currentPage < numPages; ++currentPage) {
doc.newPage(); // not needed for page 1, needed for >1
PdfTemplate template= cb.createTemplate(pageWidth, pageHeight);
Graphics2D g2d= new PdfGraphics2D(template, pageWidth, pageHeight * (currentPage + 1));
view.printAll(g2d);
g2d.dispose();
cb.addTemplate(template, 0, 0);
}
doc.close();
}