如何使用虚线作为单元格边框?

时间:2013-11-21 09:42:10

标签: java itext

我正在尝试使用iText 2.1.0在表格中间加上虚线边框(使用过的单元格边框)。下面的代码即使在表格中间之后也会产生虚线边框。

你能否帮我解决这个问题单独为特定细胞添加活动

import java.io.FileOutputStream;

import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

public class DottedLine {

    public static final String RESULT = "Dotted.pdf";

    public static void main(String[] args) throws Exception {
        new DottedLine().createPdf(RESULT);
    }

    public void createPdf(String filename) throws Exception {

        Document document = new Document(PageSize.A4, 50, 50, 50, 50);

        PdfWriter.getInstance(document, new FileOutputStream(filename));

        document.open();

        PdfPTable tab = new PdfPTable(1);
        for (int j = 1; j <= 10; j++) {
            if (j == 5) {
                PdfPCell c1 = new PdfPCell(new Phrase("Test" + j));
                c1.setBorder(Rectangle.TOP);
                c1.setCellEvent(new dot());
                tab.addCell(c1);
            } else {
                PdfPCell c2 = new PdfPCell(new Phrase("Test " + j));
                c2.setBorder(Rectangle.TOP);
                tab.addCell(c2);
            }
        }

        document.add(tab);
        document.close();
    }

    // Cell Event to make dotted Line
    class dot implements PdfPCellEvent {

        @Override
        public void cellLayout(PdfPCell arg0, Rectangle arg1, PdfContentByte[] arg2) {
            arg0.setBorder(Rectangle.TOP);
            PdfContentByte cb = arg2[PdfPTable.LINECANVAS];
            cb.setLineDash(3f, 3f);
            cb.restoreState();
        }
    }
}

1 个答案:

答案 0 :(得分:4)

您正在使用单元格事件,但您的代码非常差。您还引入了一个PDF语法错误,如果您只使用更新版本的iText,则会收到警告。 (关于过时的iText版本的警告是有原因的。人们不应该忽视它们!)

话虽这么说,我已经做了一个例子来解决你的问题:DottedLineCell

生成的PDF是一个包含两个表的文档:dotted_line_cell.pdf

对于第一个表,我们使用表事件:

class DottedCells implements PdfPTableEvent {
    @Override
    public void tableLayout(PdfPTable table, float[][] widths,
        float[] heights, int headerRows, int rowStart,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.setLineDash(3f, 3f);
        float llx = widths[0][0];
        float urx = widths[0][widths[0].length -1];
        for (int i = 0; i < heights.length; i++) {
            canvas.moveTo(llx, heights[i]);
            canvas.lineTo(urx, heights[i]);
        }
        for (int i = 0; i < widths.length; i++) {
            for (int j = 0; j < widths[i].length; j++) {
                canvas.moveTo(widths[i][j], heights[i]);
                canvas.lineTo(widths[i][j], heights[i+1]);
            }
        }
        canvas.stroke();
    }
}

这是绘制单元格边框的最优雅方式,因为它只对所有行使用一个stroke()运算符。如果你有带rowpans的表(但你可能不关心rowpans,因为你使用的是一个不支持rowpans的过时版本的iText),这不是一个选项。

第二个表使用单元格事件:

class DottedCell implements PdfPCellEvent {
    @Override
    public void cellLayout(PdfPCell cell, Rectangle position,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.setLineDash(3f, 3f);
        canvas.rectangle(position.getLeft(), position.getBottom(),
            position.getWidth(), position.getHeight());
        canvas.stroke();
    }
}

使用单元格事件,每个单元格周围都会绘制一个边框。这意味着您将拥有多个stroke()运算符和重叠行。

我是否可以再次恳求您升级到更新的版本?前iText 5版本有一个特殊的错误,导致表行在十亿行中消失一次。