从每页 itext 7 java 的第一段中删除前导
Remove Leading from the first Paragraph on every page itext 7 java
我需要删除每页第一段中的前导 属性(固定前导)?
PdfDocument pdf = new PdfDocument(new PdfWriter(DEST));
Document document = new Document(pdf);
setGridForFirstPage(pdf);
document.setMargins(0, 25, 25, 25);
String line = "Hello! Welcome to iTextPdf";
Paragraph el = new Paragraph(line);
Div div = new Div();
for (int i = 0; i < 30; i++) {
Paragraph element = new Paragraph();
element.add(line + " " + i);
element.setFixedLeading(130);
div.add(element);
}
LayoutResult result = div.createRendererSubTree().setParent(document.getRenderer()).layout(new LayoutContext(new LayoutArea(0, document.getPdfDocument().getDefaultPageSize())));
LayoutResult savePageResult = null;
deleteProperties(result);
savePageResult = div.createRendererSubTree().setParent(document.getRenderer()).layout(new LayoutContext(new LayoutArea(0, document.getPdfDocument().getDefaultPageSize())));
LayoutResult nextPageResult = savePageResult.getOverflowRenderer().layout(new LayoutContext(new LayoutArea(3, document.getPdfDocument().getDefaultPageSize())));
deleteProperties(nextPageResult);
document.add(div);
document.close();
}
private static void deleteProperties(LayoutResult childRendererListParagraph) {
List<IRenderer> childRenderers = childRendererListParagraph.getSplitRenderer().getChildRenderers();
for (int j = 0; j < childRenderers.size(); j++) {
IRenderer iRendererList = childRenderers.get(j);
if (j == 0) {
if (iRendererList != null && iRendererList.getModelElement().hasProperty(33)) {
iRendererList.getModelElement().deleteOwnProperty(33);
}
}
}
}
它只工作了两页,我尝试使用循环,但没有成功
你的方法似乎是合理的:我想它可以通过循环遍历所有溢出渲染器来改进(也许,有一天我会尝试并更新答案)。
然而,有一个完全不同的方法,对我来说似乎更方便和准确:为什么不覆盖 ParagraphRenderer
,这样每次对应的 Paragraph
都可以重置前导不适合页面(因此将移至下一页)。
这样的扩展 class 可能是这样的:
class CustomParagraphRenderer extends ParagraphRenderer {
public CustomParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult result = super.layout(layoutContext);
if (result.getStatus() != LayoutResult.FULL) {
if (null != result.getOverflowRenderer()) {
result.getOverflowRenderer().setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
} else {
// if overflow renderer is null, that could mean that the whole renderer will overflow
setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
}
}
return result;
}
@Override
// If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph
public IRenderer getNextRenderer() {
return new CustomParagraphRenderer((Paragraph) this.getModelElement());
}
}
我想强调的几点:
- 在这种情况下,应该始终覆盖
getNextRenderer
,否则默认渲染器将用于溢出的部分
- 最好不要像您那样更新模型元素的属性,因为如果您想重用段落,初始属性将已经消失。相反,应该更新渲染器本身的属性(它的属性优先于模型元素的属性,即段落的属性)
这就是您如何使用这样的 class。与您的代码的唯一区别是:
setNextRenderer
被调用,以便您的段落与自定义渲染器相关联
未设置第一个元素的行距
doc.setMargins(0, 25, 25, 25);
String line = "Hello! Welcome to iTextPdf";
Div div = new Div();
for (int i = 0; i < 30; i++) {
Paragraph element = new Paragraph();
element.setNextRenderer(new CustomParagraphRenderer(element));
element.add(line + " " + i);
if (0 != i) {
element.setFixedLeading(130);
}
div.add(element);
}
这就是生成的 PDF 的外观:
我需要删除每页第一段中的前导 属性(固定前导)?
PdfDocument pdf = new PdfDocument(new PdfWriter(DEST));
Document document = new Document(pdf);
setGridForFirstPage(pdf);
document.setMargins(0, 25, 25, 25);
String line = "Hello! Welcome to iTextPdf";
Paragraph el = new Paragraph(line);
Div div = new Div();
for (int i = 0; i < 30; i++) {
Paragraph element = new Paragraph();
element.add(line + " " + i);
element.setFixedLeading(130);
div.add(element);
}
LayoutResult result = div.createRendererSubTree().setParent(document.getRenderer()).layout(new LayoutContext(new LayoutArea(0, document.getPdfDocument().getDefaultPageSize())));
LayoutResult savePageResult = null;
deleteProperties(result);
savePageResult = div.createRendererSubTree().setParent(document.getRenderer()).layout(new LayoutContext(new LayoutArea(0, document.getPdfDocument().getDefaultPageSize())));
LayoutResult nextPageResult = savePageResult.getOverflowRenderer().layout(new LayoutContext(new LayoutArea(3, document.getPdfDocument().getDefaultPageSize())));
deleteProperties(nextPageResult);
document.add(div);
document.close();
}
private static void deleteProperties(LayoutResult childRendererListParagraph) {
List<IRenderer> childRenderers = childRendererListParagraph.getSplitRenderer().getChildRenderers();
for (int j = 0; j < childRenderers.size(); j++) {
IRenderer iRendererList = childRenderers.get(j);
if (j == 0) {
if (iRendererList != null && iRendererList.getModelElement().hasProperty(33)) {
iRendererList.getModelElement().deleteOwnProperty(33);
}
}
}
}
它只工作了两页,我尝试使用循环,但没有成功
你的方法似乎是合理的:我想它可以通过循环遍历所有溢出渲染器来改进(也许,有一天我会尝试并更新答案)。
然而,有一个完全不同的方法,对我来说似乎更方便和准确:为什么不覆盖 ParagraphRenderer
,这样每次对应的 Paragraph
都可以重置前导不适合页面(因此将移至下一页)。
这样的扩展 class 可能是这样的:
class CustomParagraphRenderer extends ParagraphRenderer {
public CustomParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult result = super.layout(layoutContext);
if (result.getStatus() != LayoutResult.FULL) {
if (null != result.getOverflowRenderer()) {
result.getOverflowRenderer().setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
} else {
// if overflow renderer is null, that could mean that the whole renderer will overflow
setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
}
}
return result;
}
@Override
// If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph
public IRenderer getNextRenderer() {
return new CustomParagraphRenderer((Paragraph) this.getModelElement());
}
}
我想强调的几点:
- 在这种情况下,应该始终覆盖
getNextRenderer
,否则默认渲染器将用于溢出的部分 - 最好不要像您那样更新模型元素的属性,因为如果您想重用段落,初始属性将已经消失。相反,应该更新渲染器本身的属性(它的属性优先于模型元素的属性,即段落的属性)
这就是您如何使用这样的 class。与您的代码的唯一区别是:
setNextRenderer
被调用,以便您的段落与自定义渲染器相关联未设置第一个元素的行距
doc.setMargins(0, 25, 25, 25); String line = "Hello! Welcome to iTextPdf"; Div div = new Div(); for (int i = 0; i < 30; i++) { Paragraph element = new Paragraph(); element.setNextRenderer(new CustomParagraphRenderer(element)); element.add(line + " " + i); if (0 != i) { element.setFixedLeading(130); } div.add(element); }
这就是生成的 PDF 的外观: