【发布时间】:2021-08-30 13:09:02
【问题描述】:
这个问题是this的后续问题 在上一篇文章之后,我设法创建了以下方法,该方法适合段落中某些空间的文本。
public static void getPlainFill2(String str, Document doc, PdfDocument document, Paragraph root,
Paragraph space, boolean isCentred) {
// System.out.println("prevText: "+prev.getText());
float width = doc.getPageEffectiveArea(PageSize.A4).getWidth();
float height = doc.getPageEffectiveArea(PageSize.A4).getHeight();
if (str.isEmpty() || str.isBlank()) {
str = "________";
}
IRenderer spaceRenderer = space.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult spaceResult = spaceRenderer
.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
Rectangle rectSpaceBox = ((ParagraphRenderer) spaceRenderer).getOccupiedArea().getBBox();
float writingWidth = rectSpaceBox.getWidth();
float writingHeight = rectSpaceBox.getHeight();
Rectangle remaining = doc.getRenderer().getCurrentArea().getBBox();
float yReal = remaining.getTop() + 2f;// orig 4f
float sizet = 0;
for (int i = 0; i < root.getChildren().size(); i++) {
IElement e = root.getChildren().get(i);
if (e.equals(space)) {
break;
}
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
sizet += ss.getOccupiedArea().getBBox().getWidth();
System.out.println("width: " + width + " current: " + sizet);
}
float start = sizet+doc.getLeftMargin();
if(isCentred)
start = (width - getRealWidth(doc, root,width,height))/2+doc.getLeftMargin()+sizet;
Rectangle towr = new Rectangle(start, yReal, writingWidth, writingHeight);// sizet+doc.getLeftMargin()
PdfCanvas pdfcanvas = new PdfCanvas(document.getFirstPage());
Canvas canvas = new Canvas(pdfcanvas, towr);
canvas.setTextAlignment(TextAlignment.CENTER);
canvas.setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph paragraph = new Paragraph(str).setTextAlignment(TextAlignment.CENTER).setBold();//.setMultipliedLeading(0.9f);
Div lineDiv = new Div();
lineDiv.setVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.add(paragraph);
float fontSizeL = 1f;
float fontSizeR = 12;
int adjust = 0;
while (Math.abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
lineDiv.setFontSize(curFontSize);
// It is important to set parent for the current element renderer to a root
// renderer
IRenderer renderer = lineDiv.createRendererSubTree().setParent(canvas.getRenderer());
LayoutContext context = new LayoutContext(new LayoutArea(1, towr));
if (renderer.layout(context).getStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
} else {
fontSizeR = curFontSize;
}
if(adjust>=2) {
writingHeight -=1.3f;
yReal += 1.4f;
adjust= 0;
}
}
lineDiv.setFontSize(fontSizeL);
canvas.add(lineDiv);
// border
// PdfCanvas(document.getFirstPage()).rectangle(towr).setStrokeColor(ColorConstants.BLACK).stroke();
canvas.close();
}
public static float getRealWidth (Document doc, Paragraph root,float width,float height) {
float sizet = 0;
for(int i = 0;i<root.getChildren().size();i++) {
IElement e = root.getChildren().get(i);
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width,height))));
sizet +=ss.getOccupiedArea().getBBox().getWidth();
}
return sizet;}
现在这几乎可以正常工作了,当文本缩放到较小的尺寸时会出现一些小问题,如下所示: https://i.ibb.co/MkxfwjQ/Screenshot-from-2021-06-14-18-27-09.png(我无法发布图片,因为我没有代表。) 但主要问题是您必须逐行编写段落才能工作。下一个例子:
Cell cell3 = new Cell();
LineCountingParagraph line3 = new LineCountingParagraph("");
Text ch07 = new Text("Paragraph Prev ");
line3.add(ch07);
Paragraph nrZile = getEmptySpace(15);
line3.add(nrZile);
Text ch08 = new Text("afterStr, textasdsadasdas ");
line3.add(ch08);
Paragraph data = getEmptySpace(18);
line3.add(data);
Text ch09 = new Text(".\n");
line3.add(ch09);
line3.setTextAlignment(TextAlignment.CENTER);
cell3.add(line3);
doc.add(cell3);
getPlainFill2("thisisalongstring", doc, document, line3, nrZile, true);
getPlainFill2("1333", doc, document, line3, data, true);
Cell cell4 = new Cell();
LineCountingParagraph line4 = new LineCountingParagraph("");
Paragraph loc2 = getEmptySpace(30);
line4.add(loc2);
Text pr32 = new Text(" aasdbsadasd ");
line4.add(pr32);
Paragraph nr2 = getEmptySpace(8);
line4.add(nr2);
Text pr33 = new Text(" asdasdasdasd.\n");
line4.add(pr33);
line4.setTextAlignment(TextAlignment.CENTER);
cell4.add(line4);
doc.add(cell4);
getPlainFill2("1333", doc, document, line4, nr2, true);
如果您需要更多代码,我会将其上传到某个地方。 现在有没有办法在多行的同一段落中插入文本?因为似乎我找不到检测 IText 7.1.11 中换行符的方法。
完整代码:
package pdfFill;
import java.io.File;
import java.io.IOException;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Div;
import com.itextpdf.layout.element.IElement;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.ParagraphRenderer;
public class Newway4 {
public static void main(String[] args) {
PdfWriter writer;
try {
writer = new PdfWriter(new File("test4.pdf"));
PdfDocument document = new PdfDocument(writer);
document.getDocumentInfo().addCreationDate();
document.getDocumentInfo().setAuthor("Piri");
document.getDocumentInfo().setTitle("Test_Stackoverflow");
document.setDefaultPageSize(PageSize.A4);
Document doc = new Document(document);
doc.setFontSize(12);
final Paragraph titlu = new Paragraph();
final Text t1 = new Text("\n\n\n\nTest Stackoverflow\n\n\n").setBold().setUnderline();
titlu.setHorizontalAlignment(HorizontalAlignment.CENTER);
titlu.setTextAlignment(TextAlignment.CENTER);
titlu.add(t1).setBold();
doc.add(titlu);
Cell cell1 = new Cell();
LineCountingParagraph line1 = new LineCountingParagraph("");
line1.add( addTab());
Text ch01 = new Text("This is the 1st example ");
line1.add(ch01);
Paragraph name = getEmptySpace(42);
line1.add(name);// cnp new line
Text ch02 = new Text(" that works ");
line1.add(ch02);
Paragraph domiciliu = getEmptySpace(63);
line1.add(domiciliu);
/* Text ch03 = new Text("\njudet");
line1.add(ch03);
Paragraph judet = getEmptySpace(12);
line1.add(judet);*/
Text ch031 = new Text("\n");
line1.add(ch031);
cell1.add(line1);
doc.add(cell1);
getPlainFill2("with insertion str", doc, document, line1, name, false);
getPlainFill2("because is writtin line by line", doc, document, line1, domiciliu, false);
Cell cell2 = new Cell();
LineCountingParagraph line2 = new LineCountingParagraph("");
Text p51 = new Text("as you can see in this");
line2.add(p51);
Paragraph localitatea = getEmptySpace(30);
line2.add(localitatea);
Text p7 = new Text(" and ");
line2.add(p7);
Paragraph nrCasa =getEmptySpace(8);
line2.add(nrCasa);
Text p09 = new Text(" of text scalling ");
line2.add(p09);
Paragraph telefon = getEmptySpace(22);
line2.add(telefon);
Text p11 = new Text(".");
line2.add(p11);
line2.setTextAlignment(TextAlignment.CENTER);
cell2.add(line2);
doc.add(cell2);
getPlainFill2("sentence", doc, document, line2, localitatea, true);
getPlainFill2("example", doc, document, line2, nrCasa, true);
getPlainFill2("text scalling bla bla", doc, document, line2, telefon, true);
doc.add(new Paragraph("\n\n\n"));
LineCountingParagraph paragraphTest = new LineCountingParagraph("");
paragraphTest.add(addTab());
Text testch01 = new Text("This is the 2nd example ");
paragraphTest.add(testch01);
Paragraph emptyTest01 = getEmptySpace(42);
paragraphTest.add(emptyTest01);
Text testch02 = new Text(" that doesn't work ");
paragraphTest.add(testch02);
Paragraph emptyTest02 = getEmptySpace(53);
paragraphTest.add(emptyTest02);
Text testch04 = new Text(" this next goes to the next line but ");
paragraphTest.add(testch04);
Paragraph emptyTest03 = getEmptySpace(42);
paragraphTest.add(emptyTest03);
Text testch05 = new Text(" won't appear !!");
paragraphTest.add(testch05);
doc.add(paragraphTest);
getPlainFill2("with insertion str", doc, document, paragraphTest, emptyTest01, false);
getPlainFill2("because next text goes next line", doc, document, paragraphTest, emptyTest02, false);
getPlainFill2("this text", doc, document, paragraphTest, emptyTest03, false);
doc.close();
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getStrWithDots(final int dots, final String str) {
final int strSize = str.length();
final StringBuilder sb = new StringBuilder();
int dotsRemained;
if (strSize > dots) {
dotsRemained = 0;
} else {
dotsRemained = dots - strSize;
}
for (int i = 0; i < dotsRemained; ++i) {
if (i == dotsRemained / 2) {
sb.append(str);
}
sb.append(".");
}
return sb.toString();
}
public static void getPlainFill2(String str, Document doc, PdfDocument document, Paragraph root,
Paragraph space, boolean isCentred) {
// System.out.println("prevText: "+prev.getText());
float width = doc.getPageEffectiveArea(PageSize.A4).getWidth();
float height = doc.getPageEffectiveArea(PageSize.A4).getHeight();
if (str.isEmpty() || str.isBlank()) {
str = "________";
}
IRenderer spaceRenderer = space.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult spaceResult = spaceRenderer
.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
Rectangle rectSpaceBox = ((ParagraphRenderer) spaceRenderer).getOccupiedArea().getBBox();
float writingWidth = rectSpaceBox.getWidth();
float writingHeight = rectSpaceBox.getHeight();
Rectangle remaining = doc.getRenderer().getCurrentArea().getBBox();
float yReal = remaining.getTop() + 2f;// orig 4f
float sizet = 0;
for (int i = 0; i < root.getChildren().size(); i++) {
IElement e = root.getChildren().get(i);
if (e.equals(space)) {
break;
}
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
sizet += ss.getOccupiedArea().getBBox().getWidth();
}
float start = sizet+doc.getLeftMargin();
if(isCentred)
start = (width - getRealWidth(doc, root,width,height))/2+doc.getLeftMargin()+sizet;
Rectangle towr = new Rectangle(start, yReal, writingWidth, writingHeight);// sizet+doc.getLeftMargin()
PdfCanvas pdfcanvas = new PdfCanvas(document.getFirstPage());
Canvas canvas = new Canvas(pdfcanvas, towr);
canvas.setTextAlignment(TextAlignment.CENTER);
canvas.setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph paragraph = new Paragraph(str).setTextAlignment(TextAlignment.CENTER).setBold();//.setMultipliedLeading(0.9f);//setbold oprtional
Div lineDiv = new Div();
lineDiv.setVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.add(paragraph);
float fontSizeL = 0.0001f, fontSizeR= 10000;
int adjust = 0;
while (Math.abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
lineDiv.setFontSize(curFontSize);
// It is important to set parent for the current element renderer to a root
// renderer
IRenderer renderer = lineDiv.createRendererSubTree().setParent(canvas.getRenderer());
LayoutContext context = new LayoutContext(new LayoutArea(1, towr));
if (renderer.layout(context).getStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
if (++adjust>1)
towr.setHeight(towr.getHeight()-0.90f);
} else {
fontSizeR = curFontSize;
}
}
lineDiv.setFontSize(fontSizeL);
canvas.add(lineDiv);
new PdfCanvas(document.getFirstPage()).rectangle(towr).setStrokeColor(ColorConstants.BLACK).stroke();
canvas.close();
}
public static Text addTab() {
StringBuilder sb = new StringBuilder();
for(int i = 0;i<8;i++)
sb.append("\u00a0");
return new Text(sb.toString());
}
public static float getRealWidth (Document doc, Paragraph root,float width,float height) {
float sizet = 0;
for(int i = 0;i<root.getChildren().size();i++) {
IElement e = root.getChildren().get(i);
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width,height))));
sizet +=ss.getOccupiedArea().getBBox().getWidth();
}
return sizet;
}
private static Paragraph getEmptySpace(int size) {
Paragraph space = new Paragraph();
space.setMaxWidth(size);
for(int i=0;i<size;i++) {
// par.add("\u00a0");
space.add("\u00a0");
}
return space;
}
private static class LineCountingParagraph extends Paragraph {
private int linesWritten = 0;
public LineCountingParagraph(String text) {
super(text);
}
public void addWrittenLines(int toAdd) {
linesWritten += toAdd;
}
public int getNumberOfWrittenLines() {
return linesWritten;
}
@Override
protected IRenderer makeNewRenderer() {
return new LineCountingParagraphRenderer(this);
}
}
private static class LineCountingParagraphRenderer extends ParagraphRenderer {
public LineCountingParagraphRenderer(LineCountingParagraph modelElement) {
super(modelElement);
}
@Override
public void drawChildren(DrawContext drawContext) {
((LineCountingParagraph)modelElement).addWrittenLines(lines.size());
super.drawChildren(drawContext);
}
@Override
public IRenderer getNextRenderer() {
return new LineCountingParagraphRenderer((LineCountingParagraph) modelElement);
}
}
}
问题:在 PDF 的上半部分,您可以看到创建了两个 LineCountingParagraph 实例的结果,每行一个。在 PDF 的下半部分,您可以看到仅创建一个 LineCountingParagraph 实例时的结果。因此,如果段落的内容换行到下一行,则将文本放入框中并不能很好地工作。
【问题讨论】:
-
能否添加
getEmptySpace和LineCountingParagraph的声明?没有它们,代码无法编译。如果您在没有行计数的情况下附加视觉结果(因此结果对您来说是有问题的)和带有计数的结果,那也很好,这样您就可以清楚地了解您正在寻找的行为是什么 -
我将代码写在一个文件中。 pastebin.com/UKXLs3zg
-
有这方面的消息吗?以前的 pastebin 链接已过期,所以这是一个新链接 pastebin.com/jg2je8eA