在之前的章节中,我们讨论了实现AbstractElement
类的5个类。在章节2中,我们讨论了AreaBreak
类。在章节3中我们讨论了实现ILeafElement
类的4个类——Tab
、Link
、Text
和Image
类。在这章节,我们会着重于其他一系列实现AbstractElement
的类。如用于分组元素的Div
类和用于在元素之间划线的LineSeparator
。我们在之前的章节中已经多次使用过Paragraph
类,但是在本章中我们将会重新讨论它。最后我们将讨论List
类和ListItem
类,而Table
和Cell
类将会在下一章节中讲述。
Div
类是BlockElement
类的实现,可以用来分组不同的元素。在图4.1中,我们可以看到Jekyll and Hyde
系列电影的概览。其中每个条目包含最多三种元素:
Paragraph
显示电影的标题;Paragraph
显示导演、国家和年份;Image
显示电影海报(如果有的话); 我们将这个三个元素组合在一个Div
中,并为这个Div
定义了左边框、左填充和下边距。
整体代码如下:
public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdf);
List> resultSet = CsvTo2DList.convert(SRC, "|");
resultSet.remove(0);
for (List record : resultSet) {
Div div = new Div()
.setBorderLeft(new SolidBorder(2))
.setPaddingLeft(3)
.setMarginBottom(10);
String url = String.format(
"https://www.imdb.com/title/tt%s", record.get(0));
Link movie = new Link(record.get(2), PdfAction.createURI(url));
div.add(new Paragraph(movie.setFontSize(14)))
.add(new Paragraph(String.format(
"Directed by %s (%s, %s)",
record.get(3), record.get(4), record.get(1))));
File file = new File(String.format(
"src/main/resources/img/%s.jpg", record.get(0)));
if (file.exists()) {
Image img = new Image(
ImageDataFactory.create(file.getPath()));
img.scaleToFit(10000, 120);
div.add(img);
}
document.add(div);
}
document.close();
}
和往常一样,我们创建一个PdfDocument
和一个Document
实例(第2-3行)。其中CSV文件我们重用了前一章节介绍的CSV文件,并遍历这个文件,列出所有电影,不包括标题行(行4-6)。我们创建另一个新的Div
对象(行7),将它的左边框定义为2个用户单位的实心边框(行8),并将做填充设置为3个用户单位(行9),下边距设置为10个用户单位(行10)。紧接着我们电影标题Paragraph
(行14)和其他信息(行15-17)添加到这个Div
中。如果我们可以找到到电影海报,我们会添加Image
对象(行24)。最后添加每一个Div
到Document
中并且关闭这个Document
。
我们把目光放在第一页的底部和第二页的顶部,也就是电影标题是Dr. Jekyll and Mr. Hyde
,导演是John S. Roberson
的Div
分布到两页上。电影海报在第一页上放不下,所以被放到了第二页。当然这可能不是我们所希望,也许我们希望添加到同一个Div
的元素保持在一起,如图4.2所示:
我们只需要用一个额外的方法来做到如此,代码如下:
Div div = new Div()
.setKeepTogether(true)
.setBorderLeft(new SolidBorder(2))
.setPaddingLeft(3)
.setMarginBottom(10);
通过添加setKeepTogether(true)
,告诉iText尝试将Div
的内容保持在同一页面上。如果该Div
的内容适合在下一页,则该Div
中所有的元素将被转发到下一页。在图4.2中就是这种情况,上述我们提到Dr. Jekyll and Mr. Hyde
电影的标题和信息被转发到下一页。
如果Div
的内容不适合下一页,那么此方法将会不起作用。在这种情况下,元素分部在当前页面和后续页面上,就好像未使用 setKeepTogether()
方法一样。 如果真的想将一个元素与下一个元素保持在同一页面上,有一种解决方法。 在我们讨论了 LineSeparator
对象之后,我们将看一个演示此解决方法的示例。
相信大家也看到了哈,iText里面的构建块与HTML里面的标签很类似。 代码如下: 首先我们传递了厚度参数来创建了一个 我们将 关于 在前面的示例中,我们已经多次使用 如图4.4中展示了我们需要修复的一个缺陷:在第3也上面有个标题,但是那这章的内容却在第4也上面。 这种问题我们应该尽量避免,让标题和内容在同一页面上,首先让我们做第一次尝试,采用的代码如下: 上面代码和我们第2章写的很相似,最主要的区别就是我们不再直接把 我们可以在第 15 行和第 16 行之间尝试添加 如下代码展示了如何使用: 首先把一个 有两种方法可以改变段落的行距: 这两个方法是相互排斥的。 如果在同一个段落中同时使用这两种方法,则以最后调用的方法为准。 图 4.6 展示了读取这个故事的另一种转换: 总页数较低,因为我们通过添加 . 实现上述的代码除了以下代码片段以外,和之前的例子几乎一样: 当我们直接或间接(例如通过 看如图4.7所示,有两个不同背景的 让我们看看实现上述效果的代码片段,首先是第一个 然后是第二个 其中用到的 我们继承了现有的类 最后让我们看看 如图4.8显示了默认可用的不同类型的列表。其中有编号列表(罗马数字和阿拉伯数字)、带有字母的列表(小写、大写、拉丁、希腊)等等。 下面代码是前面三种列表如何添加: 行1我们首先声明了没有类型的 创建不同类型的列表的参数是一个枚举类: 显然,我们也可以定义自己的自定义列表符号,或者我们可以使用默认列表符号(例如数字)的组合并将它们与前缀或后缀组合。 效果如图 4.9 所示。 首先我们看一下如何引入一个简单的项目符号作为列表符号,而不是默认的连字符。代码片段如下: 我们创建一个 在这里我们将列表符号设置为 第1行创建了一个 在默认列表类型中,iText 总是在编号列表的列表符号后添加一个点:a.、b.、c. 等。 有的时候我们不想要这个点或者用其他符号替换“.”,例如:a-、b-、c- 等等。 下面的代码片段展示了如何实现这一点: 第 1 行和第 2 行相当于 还有一个 并非每个编号列表都需要以 1、i、a 等开头。 你还可以使用 最后,我们将使用 到目前为止,我们一直使用字符串将列表项添加到列表中, 其实这些 在第0章的类图里面,我们可以看到 以本章第一个例子为引,我们不用 代码和 先解析数据到 本章最后一个例子是创建嵌套列表,展示的效果如图4.11所示: 这个例子里面变量很难多,看起来比较绕,又复杂,所以我们简单拆成几部分来讲。首先我们从一个常规列表开始,变量名称为list。 我们创建一个数字列表list1(行1)。这个列表有两个 对应图4.11所示,首先是分割符,然后可以看见数字列表符号1. 和 2. ,同时内部嵌套了两个使用小写英文字母的列表元素的列表。 在下一个代码片段,我们创建了另一个属于list的 此外,我们创建了一个带有编号的ZapfDingbats项目符号列表(listZ1),并把这个列表添加到列表元素(变量名为liZ1): 接着创建第二个带有不同ZapfDingbats项目符号的列表(listZ2),并把这个列表添加到列表元素(变量名为liZ2): 接着创建第三个带有不同ZapfDingbats项目符号的列表(listZ3),并把这个列表添加到列表元素(变量名为liZ3): 最后创建第四个带有不同ZapfDingbats项目符号的列表(listZ4),并把这个列表添加到列表元素(变量名为liZ4): 接着我们做如下的事情来完成嵌套: 最后我们把list添加到 最终的效果如上图所属,列表的某个元素可以为列表。 在本章中,我们讨论了构建块 下一章我们把目光聚集在表格,具体就是 Text
大致对应
(空标签),Paragraph
对应标签,
Div
对应LineSeparator
最好的对应标签为
。图 4.3 显示了一条由红线组成的水平线,1 个用户单位粗,占可用宽度的 50%,为此定义了 5 个用户单位的上边距。
SolidLine line = new SolidLine(1f);
line.setColor(Color.RED);
LineSeparator ls = new LineSeparator(line);
ls.setWidthPercent(50);
ls.setMarginTop(5);
SolidLine
对象。在这里我们回顾一下,在上一章中,SolidLine
是 ILineDrawer
接口的实现之一。 然后将其颜色设置为红色,并使用此 ILineDrawer
创建 LineSeparator
实例。 接着使用 setWidthPercent()
方法定义线条的宽度。 当然我们也可以使用 setWidth()
方法来定义以用户单位表示的绝对宽度。 最后,我们将上边距设置为 5 个用户单位。ls
对象添加到包含电影信息的Div
元素中。div.add(ls);
LineSeparator
基本上就是这些内容。我们只需要记住我们应该使用正确的方法来设置属性。例如:在LineSeparator
层面不能改变线的颜色,需要在ILineDrawer
层面设置。显得宽度也是如此。我们可以查验附录B来看LineSeparator
类实现了哪些 AbstractElement
方法,以及忽略了哪些方法。3. 让内容保持在一起
Paragraph
类。 例如:在第 2 章中,我们使用 Paragraph
类将文本文件转换为 PDF,方法是为文本文件中的每一行创建一个 Paragraph
对象,并将所有这些 Paragraph
对象添加到 Document
实例中 . 前几章的屏幕截图表明,我们可以制作一些非常好的 PDF 文档,但总有改进的余地。public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdf);
PdfFont font = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
PdfFont bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
document.setTextAlignment(TextAlignment.JUSTIFIED)
.setHyphenation(new HyphenationConfig("en", "uk", 3, 3));
BufferedReader br = new BufferedReader(new FileReader(SRC));
String line;
Div div = new Div();
while ((line = br.readLine()) != null) {
Paragraph title = new Paragraph(line)
.setFont(bold).setFontSize(12)
.setMarginBottom(0);
div = new Div()
.add(title)
.setFont(font).setFontSize(11)
.setMarginBottom(18);
while ((line = br.readLine()) != null) {
div.add(
new Paragraph(line)
.setMarginBottom(0)
.setFirstLineIndent(36)
);
if (line.isEmpty()) {
document.add(div);
break;
}
}
}
document.add(div);
document.close();
}
Paragrah
添加到Document
中。相反,我们把Paragrah
添加到Div
中,然后在每个章节的末尾把Div
添加到Paragrah
中。但是最终我们发现并能做到我们想要的结果。.setKeepTogether(true)
,但这不会产生任何影响,因为 Div
里面全部内容在单个页面里面放不下。 这个也提到过了, setKeepTogether()
方法会被忽略。 iText 上就如何解决这个问题进行了长时间的研究, 最终定避免寡居对象的最优雅方法是引入 setKeepWithNext()
方法。
setKeepWithNext()
方法是在 iText 7.0.1 中引入的。 第一个 iText 7 版本中找不到这个方法。 iText正在研究是否可以支持嵌套对象的方法, 但是不愿意这样做,因为这可能会对库的整体性能产生重大的负面影响。BufferedReader br = new BufferedReader(new FileReader(SRC));
String line;
Div div = new Div();
while ((line = br.readLine()) != null) {
document.add(new Paragraph(line)
.setFont(bold).setFontSize(12)
.setMarginBottom(0)
.setKeepWithNext(true));
div = new Div()
.setFont(font).setFontSize(11)
.setMarginBottom(18);
while ((line = br.readLine()) != null) {
div.add(
new Paragraph(line)
.setMarginBottom(0)
.setFirstLineIndent(36)
);
if (line.isEmpty()) {
document.add(div);
break;
}
}
}
document.add(div);
Paragraph
直接添加到Document
(行5);然后创建一个Div
来容纳章节剩余内容(行9)。通过添加 setKeepWithNext(true)
来表明 Paragraph
需要与 Div
的(第一部分)保持在同一页面上。 结果如图 4.5所示。 与图 4.4相比,标题“SEARCH FOR MR. HYDE”现在被转发到下一页。setKeepWithNext()
方法可以与除 Cell
之外的所有其他 AbstractElement
的实现类一起使用。 该方法仅适用于直接添加到 Document
实例的元素。 它不适用于嵌套对象,例如始终添加到表格而不直接添加到文档的Cell
。 在上面示例中,如果标题 Paragraph
被添加到 Div
而不是 Document
,它将不起作用。4. 更改段落行距
Paragraph
类除了实现 AbstractElement
级别定义的方法之上还有一些额外的方法。 我们已经使用了上一章中涉及 TabStops
的方法(制表符/制表位)。 上面的例子里面还引用了 setFirstLineIndent()
方法(改变缩进)。 现在我们将目光放在如何研究行距。
行距-英文leading这个词发音为ledding,它来自铅(金属)这个词。 当为印刷机手动设置字体时,铅条被放置在字体行之间以增加空间。 这个词最初指的是放置在线条之间的这些铅条的厚度。 PDF 标准将前导重新定义为“相邻文本行的基线之间的垂直距离”(ISO-32000-1,第 9.3.5 节)。setFixedLeading()
—— 将行距更改为绝对值。 例如:如果定义 18 的固定行距,则两行文本的基线之间的距离将为 18 个用户单位。setMultipliedLeading
——将行距更改为相对于字体大小的值。 例如,如果定义乘以 1.5f 的行距并且字体为 12 pt,那么前导将为 18 个用户单位(即 1.5 乘以 12)。setMultipliedLeading(1.2f)
更改了行之间的距离。div.add(
new Paragraph(line)
.setMarginBottom(0)
.setFirstLineIndent(36)
.setMultipliedLeading(1.2f)
);
Div
)将对象添加到 Document
时,iText 使用适当的 IRenderer
将此对象呈现为 PDF。 在本系列第0章的图 4 里面展示了不同渲染器的概览。一般情况下我们使用 iText 几乎不需要创建自定义渲染器,但我们将看一个示例,在这个示例中我们创建了一个继承(extends)默认 ParagraphRenderer
的 MyParagraphRenderer
。5. 创建自定义渲染器
Paragraph
s。对于第一个Paragraph
,我们使用了.setBackgroundColor()
方法,这个方法基于段落的位置画了一个矩形,对于第二个Paragraph
,我想要画一个圆角矩形。但是iText 7里面没有方法来做到,做到这我们需要写一个自定义ParagraphRenderer
类。Paragraph
,代码如此:Paragraph p1 = new Paragraph(
"The Strange Case of Dr. Jekyll and Mr. Hyde");
p1.setBackgroundColor(Color.ORANGE);
document.add(p1);
Paragraph
,代码如此:Paragraph p2 = new Paragraph(
"The Strange Case of Dr. Jekyll and Mr. Hyde");
p2.setBackgroundColor(Color.ORANGE);
p2.setNextRenderer(new MyParagraphRenderer(p2));
document.add(p2);
MyParagraphRenderer
的定义如下:class MyParagraphRenderer extends ParagraphRenderer {
public MyParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public void drawBackground(DrawContext drawContext) {
Background background =
this.<Background>getProperty(Property.BACKGROUND);
if (background != null) {
Rectangle bBox = getOccupiedAreaBBox();
boolean isTagged =
drawContext.isTaggingEnabled()
&& getModelElement() instanceof IAccessibleElement;
if (isTagged) {
drawContext.getCanvas().openTag(new CanvasArtifact());
}
Rectangle bgArea = applyMargins(bBox, false);
if (bgArea.getWidth() <= 0 || bgArea.getHeight() <= 0) {
return;
}
drawContext.getCanvas().saveState()
.setFillColor(background.getColor())
.roundRectangle(
(double)bgArea.getX() - background.getExtraLeft(),
(double)bgArea.getY() - background.getExtraBottom(),
(double)bgArea.getWidth()
+ background.getExtraLeft() + background.getExtraRight(),
(double)bgArea.getHeight()
+ background.getExtraTop() + background.getExtraBottom(),
5)
.fill().restoreState();
if (isTagged) {
drawContext.getCanvas().closeTag();
}
}
}
}
ParagraphRenderer
并且值覆写了一个方法。从AbstractRenderer
类中copy了原始的drawBackground()
方法,并且使用了roundRectangle()
(行23)代替了rectangle()
方法。行24-29里面我们注意到矩形的尺寸可以通过左侧、右侧、顶部和底部的额外空间进行微调。这些额外空间可以通过不同参数的setBackgroundColor()
方法来设置(具体为带有4个额外浮点数的变量:extraLeft, extraTop, extraRight, 和extraBottom)。List
和ListItem
的例子并结束本篇章。5. 列表和列表符号
List list = new List();
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
list = new List(ListNumberingType.DECIMAL);
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
list = new List(ListNumberingType.ENGLISH_LOWER);
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
List
。默认情况下,这将生成一个以连字符作(-
)为列表符号的列表。 然后在第 2-3 行快速 添加了2个列表项; 然后我们将List
添加到 Document
(第 4 行)。之后就是多次重复这四行,例如定义一个十进制数字列表(第 5 行),定义一个带有小写字母的字母列表(第 9 行)。ListNumberingType
,这个类有以下几种值:DECIMAL
——列表符号是阿拉伯数字:1、2、3、4、5、…ROMAN_LOWER
——列表符号是小写罗马数字:i、ii、iii、iv、v、…ROMAN_UPPER
——列表符号为大写罗马数字:I、II、III、IV、V、…ENGLISH_LOWER
—— 列表符号是小写字母(使用英文字母):a、b、c、d、e、…ENGLISH_UPPER
——列表符号是大写字母(使用英文字母):A、B、C、D、E、…GREEK_LOWER
——列表符号为小写希腊字母:α, β, γ, δ, ε,…GREEK_UPPER
——列表符号为大写希腊字母:Α、Β、Γ、Δ、Ε、…ZAPF_DINGBATS_1
——列表符号是来自 Zapfdingbats 字体的项目符号,更具体地说是 [172; 181]范围内的字符。ZAPF_DINGBATS_2
——列表符号是 Zapfdingbats 字体的项目符号,更具体地说是 [182;191]范围内的字符。ZAPF_DINGBATS_3
——列表符号是来自 Zapfdingbats 字体的项目符号,更具体地说是 [192; 201]范围内的字符。ZAPF_DINGBATS_4
——列表符号是来自 Zapfdingbats 字体的项目符号,更具体地说是 [202; 221]范围内的字符。List list = new List();
list.setListSymbol("\u2022");
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
List
并使用 setListSymbol()
方法来更改列表符号,其中可以使用任何String
作为列表符号。在我们的例子中,我们想要一个像子弹一样的原点,对应的Unicode值为/u2022
。 但是注意到子弹符号与列表项的内容非常接近。 做到这样可以通过使用 setSymbolIndent()
方法定义缩进来改变这一点,就像下面例子里面一样:list = new List();
PdfFont font = PdfFontFactory.createFont(FontConstants.ZAPFDINGBATS);
list.setListSymbol(new Text("*").setFont(font).setFontColor(Color.ORANGE));
list.setSymbolIndent(10);
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
*
,但使用的是Text
对象而不是String
。 然后将字体设置为 ZapfDingbats。最后还将字体颜色更改为橙色。 最终展示的效果会产生一个看起来像橙色手指的列表符号。 在下一个片段中,我们使用Image
对象作为列表符号:Image info = new Image(ImageDataFactory.create(INFO));
info.scaleAbsolute(12, 12);
list = new List().setSymbolIndent(3);
list.setListSymbol(info);
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
Image
对象,其中INFO
指向了蓝色信息提示的图片。然后缩放图像,使其尺寸为 12 x 12 个用户单位,并将图像作为setListSymbol()
方法的参数传递。list = new List();
list.setListSymbol(ListNumberingType.ENGLISH_LOWER);
list.setPostSymbolText("- ");
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
list = new List(ListNumberingType.ENGLISH_LOWER)
; 它会生成一个使用英文字母的编号列表。 然后我们使用setPostSymbolText(
方法将每个字母后自动添加的点替换为“-”。setPreSymbolText()
方法可以在默认列表符号前面添加文本。 以下代码片段创建了一个十进制列表(1.、2.、3.、…),但通过添加前符号和后符号,列表符号已成为如下所示的列表标签:Part 1: ,Part 2:,Part 3 :,等等。list = new List(ListNumberingType.DECIMAL);
list.setPreSymbolText("Part ");
list.setPostSymbolText(": ");
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
setItemStartIndex()
方法选择以更大的数字(或字母)开头。 在以下代码示例中,我们从 5 开始计数。list = new List(ListNumberingType.DECIMAL);
list.setItemStartIndex(5);
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
document.add(list);
setListSymbolAlignment()
来更改标签的对齐方式。 例如图 4.8中的小写罗马数字列表与图 4.9 中的列表进行比较,你会发现列表标签的对齐方式有所不同。list = new List(ListNumberingType.ROMAN_LOWER);
list.setListSymbolAlignment(ListSymbolAlignment.LEFT);
for (int i = 0; i < 6; i++) {
list.add("Dr. Jekyll");
list.add("Mr. Hyde");
}
document.add(list);
String
值在内部更改为ListItems
。7. 将 ListItem 对象添加到List
ListItem
类是Div
类的子类。和Div
一样类似,我们可以在列表上下文里面添加不同对象。Div
而使用ListItem
s,展现的效果如图10所示Div
的例子很像:public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdf);
List<List<String>> resultSet = CsvTo2DList.convert(SRC, "|");
resultSet.remove(0);
com.itextpdf.layout.element.List list =
new com.itextpdf.layout.element.List(ListNumberingType.DECIMAL);
for (List record : resultSet) {
ListItem li = new ListItem();
li.setKeepTogether(true);
String url = String.format(
"https://www.imdb.com/title/tt%s", record.get(0));
Link movie = new Link(record.get(2), PdfAction.createURI(url));
li.add(new Paragraph(movie.setFontSize(14)))
.add(new Paragraph(String.format(
"Directed by %s (%s, %s)",
record.get(3), record.get(4), record.get(1))));
File file = new File(String.format(
"src/main/resources/img/%s.jpg", record.get(0)));
if (file.exists()) {
Image img = new Image(ImageDataFactory.create(file.getPath()));
img.scaleToFit(10000, 120);
li.add(img);
}
list.add(li);
}
document.add(list);
document.close();
}
java.util.List
(行4),然后声明了全路径com.itextpdf.layout.element.List
来避免编译器混淆(行6),并创建了数字列表(行7)。接着为java.util.List
中的每个项目创建一个ListItem
(行9)。然后添加Paragraph
s和Image
(如果有的话)添加到这个ListItem
中(行11-24)。最后我们把每个ListItem
添加到List
中(行25),最终把这个List
添加到Document
中。8. 嵌套列表
List list = new List();
ListItem
s,liEL(行5)和liEU(行11)。同时对应这两个ListItem
创建对应的List
:listEL(行2,小写英文字母)和listEU(行8,大写英文字母),并为每个List
添加列表元素“Dr. Jekyll”和“Mr. Hyde”。(行3-4,行9-10)。List list1 = new List(ListNumberingType.DECIMAL);
List listEL = new List(ListNumberingType.ENGLISH_LOWER);
listEL.add("Dr. Jekyll");
listEL.add("Mr. Hyde");
ListItem liEL = new ListItem();
liEL.add(listEL);
list1.add(liEL);
List listEU = new List(ListNumberingType.ENGLISH_UPPER);
listEU.add("Dr. Jekyll");
listEU.add("Mr. Hyde");
ListItem liEU = new ListItem();
liUL.add(listEU);
list1.add(liEU);
ListItem li1 = new ListItem();
li1.add(list1);
list.add(li1);
ListItem
,对应变量名称为li
(行1)。然后我们往这个ListItem
添加4个列表:listGL(行2),listGU(行6),listRL(行10)和listRU(行14)。这些列表(希腊字母小写,希腊字母大写,罗马数字小写,罗马数字大写)依次添加到默认到具有默认列表符号的列表项。ListItem li = new ListItem();
List listGL = new List(ListNumberingType.GREEK_LOWER);
listGL.add("Dr. Jekyll");
listGL.add("Mr. Hyde");
li.add(listGL);
List listGU = new List(ListNumberingType.GREEK_UPPER);
listGU.add("Dr. Jekyll");
listGU.add("Mr. Hyde");
li.add(listGU);
List listRL = new List(ListNumberingType.ROMAN_LOWER);
listRL.add("Dr. Jekyll");
listRL.add("Mr. Hyde");
li.add(listRL);
List listRU = new List(ListNumberingType.ROMAN_UPPER);
listRU.add("Dr. Jekyll");
listRU.add("Mr. Hyde");
li.add(listRU);
list.add(li);
List listZ1 = new List(ListNumberingType.ZAPF_DINGBATS_1);
listZ1.add("Dr. Jekyll");
listZ1.add("Mr. Hyde");
ListItem liZ1 = new ListItem();
liZ1.add(listZ1);
List listZ2 = new List(ListNumberingType.ZAPF_DINGBATS_2);
listZ2.add("Dr. Jekyll");
listZ2.add("Mr. Hyde");
ListItem liZ2 = new ListItem();
liZ2.add(listZ2);
List listZ3 = new List(ListNumberingType.ZAPF_DINGBATS_3);
listZ3.add("Dr. Jekyll");
listZ3.add("Mr. Hyde");
ListItem liZ3 = new ListItem();
liZ3.add(listZ3);
List listZ4 = new List(ListNumberingType.ZAPF_DINGBATS_4);
listZ4.add("Dr. Jekyll");
listZ4.add("Mr. Hyde");
ListItem liZ4 = new ListItem();
liZ4.add(listZ4);
Document
。listZ3.add(liZ4);
listZ2.add(liZ3);
listZ1.add(liZ2);
list.add(liZ1);
document.add(list);
9. 总结
Div
、LineSeparator
、Paragraph
、List
和 ListItem
。 我们使用Div
对其他构建块进行分组,使用LineSeparator
绘制水平线。 我们解决了第 2 章示例中可能遇到的问题:如何将特定元素放在通一个页面上。 同时我们没有详细介绍IRenderer
实现,但是罗列一个示例——更改了段落绘制背景的方式。 为此创建了一个自定义的ParagraphRenderer
来实现这一点。 最后,我们创建了一些List
示例来演示不同类型的列表(编号、未编号、直截了当方式添加、嵌套添加等)。Table
和 Cell
类。