我使用PDFJet-Open-Source库来构建pdf。所以,我有几个问题:
1)如何将多行文字放在Cell中?
问题描述:目前我遇到的问题是我无法将多行文字放在Cell对象中。我尝试设置像"text1 \n text2..."
这样的文本,但它没有任何效果。不幸的是,开源版本没有TextColumn和Paragraph类。
2)什么是CompositeTextLine以及如何使用它?
问题描述:也许我的想象力错误,但我尝试做以下事情:
...
CompositeTextLine ctl = new CompositTextLine(0,0);
ctl.addComponent(new TextLine(f1,"MyText1"));
ctl.addComponent(new TextLine(f1,"MyText2"));
ctl.addComponent(new TextLine(f1,"MyText3"));
Cell cell = new Cell(f1);
cell.setCompositeTextLine(ctl);
...
我预计会在Cell中看到几行,但我什么也没看到。此外,如果我添加行table.wrapAroundCellText()
,我有 NullPointerException 。如果我拨打ctl.drawOn(page)
,我只会观察:“MyText1 MyText2 MyText3”没有断行。
UPDATE:我发现了TextBox类,所以,如果我写的话:
TextBox textbox = new TextBox(f1);
textbox.setText("First Line \n Second Line");
textbox.drawOn(page);
它将构建我想要的东西:
First Line
Second Line
但我仍然对(1)和(2)的描述以及其中一些变体的可能性感兴趣,比如“如何在Cell中设置TextBox(或图像等),而不仅仅是单行?”< / p>
最后一个,请任何人,请参考我在Java或C ++中实现“文本对齐”算法。
答案 0 :(得分:6)
我可以遇到同样的问题,我最终扩展了Cell,并使用WordUtils中的apache commons lang3:
public class MultilineCell extends Cell {
private final int characterCount;
public MultilineCell(Font font, String content, int characterCount) {
super(font, content);
this.characterCount = characterCount;
}
@Override
public String getText() {
return WrapUtil.wrap(super.getText(), this.characterCount);
}
@Override
public float getHeight() {
float height = this.font.getBodyHeight();
String text = getText();
if (text != null) {
String[] wrappedTexts = text.split(System.getProperty("line.separator"));
if (wrappedTexts.length > 1) {
return (height * wrappedTexts.length) + this.top_padding + this.bottom_padding;
}
}
return height + this.top_padding + this.bottom_padding;
}
@Override
protected void paint(Page page, float x, float y, float w, float h) throws Exception {
page.setPenColor(this.getPenColor());
page.setPenWidth(this.lineWidth);
drawBorders(page, x, y, w, h);
drawText(page, x, y, w);
}
private void drawBorders(
Page page,
float x,
float y,
float cell_w,
float cell_h) throws Exception {
if (getBorder(Border.TOP) &&
getBorder(Border.BOTTOM) &&
getBorder(Border.LEFT) &&
getBorder(Border.RIGHT)) {
page.drawRect(x, y, cell_w, cell_h);
}
else {
if (getBorder(Border.TOP)) {
page.moveTo(x, y);
page.lineTo(x + cell_w, y);
page.strokePath();
}
if (getBorder(Border.BOTTOM)) {
page.moveTo(x, y + cell_h);
page.lineTo(x + cell_w, y + cell_h);
page.strokePath();
}
if (getBorder(Border.LEFT)) {
page.moveTo(x, y);
page.lineTo(x, y + cell_h);
page.strokePath();
}
if (getBorder(Border.RIGHT)) {
page.moveTo(x + cell_w, y);
page.lineTo(x + cell_w, y + cell_h);
page.strokePath();
}
}
}
private void drawText(
Page page,
float x,
float y,
float cell_w) throws IOException {
String wrappedText = WrapUtil.wrap(super.getText(), this.characterCount);
String[] lines = wrappedText.split(System.getProperty("line.separator"));
float x_text = x + this.left_padding;
float y_text = y + this.font.getAscent() + this.top_padding;
for (String line : lines) {
page.drawString(this.font, line, x_text, y_text);
y_text += this.font.getBodyHeight();
}
}
}
您可以像使用Cell一样实例化和添加MultilineCell:
List<Cell> rowCells = new ArrayList<Cell>();
rowCells.add(new MultilineCell(font, c.getString(reasonIdx), 42));
我知道扩展不是一个很好的解决方案,并且复制drawBorders()更糟糕,但在这种情况下,如果你不想分叉PDFJet,它是唯一的解决方案。
然而,这会打破autoAdjustColumnWidths
:宽度是在整个文本上计算的,而不是最长的行。因此,如果您打算使用此方法,可以使用子类Table
,fork PDFJet,也可以只提取此方法(后者的唯一缺点是我无法解决单元格填充问题):
/**
* Auto adjusts the widths of all columns so that they are just wide enough to hold the text without truncation.
*/
private static void autoAdjustColumnWidths(List<List<Cell>> tableData) {
// Find the maximum text width for each column
float[] max_col_widths = new float[tableData.get(0).size()];
for (int i = 0; i < tableData.size(); i++) {
List<Cell> row = tableData.get(i);
for (int j = 0; j < row.size(); j++) {
Cell cell = row.get(j);
if (cell.getColSpan() == 1) {
float cellWidth = 0f;
if (cell.getImage() != null) {
cellWidth = cell.getImage().getWidth();
}
if (cell.getText() != null) {
// Is this a multiline cell? If so, measure the widest line
if (cell.getText().contains(MultilineCell.NEW_LINE)) {
String[] lines = cell.getText().split(MultilineCell.NEW_LINE);
for (String line : lines) {
if (cell.getFont().stringWidth(cell.getFallbackFont(), line) > cellWidth) {
cellWidth = cell.getFont().stringWidth(cell.getFallbackFont(), line);
}
}
}
// Standard (single-line) cell, measure whole text
else {
if (cell.getFont().stringWidth(cell.getFallbackFont(), cell.getText()) > cellWidth) {
cellWidth = cell.getFont().stringWidth(cell.getFallbackFont(), cell.getText());
}
}
}
cell.setWidth(cellWidth + 2f /*cell.left_padding*/ + 2f/*cell.right_padding*/);
if (max_col_widths[j] == 0f ||
cell.getWidth() > max_col_widths[j]) {
max_col_widths[j] = cell.getWidth();
}
}
}
}
for (int i = 0; i < tableData.size(); i++) {
List<Cell> row = tableData.get(i);
for (int j = 0; j < row.size(); j++) {
Cell cell = row.get(j);
cell.setWidth(max_col_widths[j]);
}
}
}
PDFJet是一个有趣的库,btw:受保护的字段,每个其他方法抛出异常,并且这些类绝对不是为扩展而设计的,即使它不是最终的。
答案 1 :(得分:0)
有一个棘手的解决方案: 正如之前所建议的那样,将您的输入分成几行(例如使用来自apache commons lang3的WordUtils)
String wrappedText = WrapUtil.wrap(super.getText(), this.characterCount);
String[] lines = wrappedText.split(System.getProperty("line.separator"));
获得lines
后,使用这些单独的行在表格中添加尽可能多的行。
模拟&#34;多线单元&#34;调用函数removeLineBetweenRows
提供这些添加行的索引。它看起来像一个大单元。