java - 有人可以解释一下 iTexts Canvas 绘制顺序吗?

标签 java pdf canvas itext savestate

我尝试在 iText 中绘制一些嵌套表格,因为我认为这是定位所有内容的最简单方法。

enter image description here

所以我在另一个表中有多个表,它们都有背景颜色和/或笔画(通过 PdfPCellEvents)。不幸的是,外表的笔划与内表的背景重叠。 我认为这是由于应用顺序错误或 PdfPCellEvents 中的一些错误设置 saveStaterestoreState 造成的。

谁能向我解释一下 saveStaterestoreState 的正确用法,并提示我如何正确应用背景和描边?

这是我添加条纹背景单元格的代码:

PdfPCell scaleBackground = new PdfPCell();
scaleBackground.setBorder(Rectangle.NO_BORDER);
scaleBackground.setVerticalAlignment(Element.ALIGN_TOP);
scaleBackground.setCellEvent(new StripedScaleBackground(max, scaleHeight));

StripedScaleBackground的cellLayout方法:

public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases)
{
    PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
    float llx = rect.getLeft();
    float lly = rect.getBottom();
    float urx = rect.getRight();
    float ury = rect.getTop();

    // Light scale lines with padding from left
    canvas.setLineWidth(Constants.BORDER_WIDTH_THIN);
    canvas.setColorStroke(Colors.LIGHT_GRAY);

    float paddingLeft = 22f;
    for (int i = 0; i <= this.maxValue; i++)
    {
        canvas.moveTo(llx + paddingLeft, lly + (this.scaleHeight * (i + 1)));
        canvas.lineTo(urx, lly + (this.scaleHeight * (i + 1)));
    }

    // Vertical line
    canvas.moveTo(llx + (((urx - llx) + paddingLeft) / 2), ury);
    canvas.lineTo(llx + (((urx - llx) + paddingLeft) / 2), lly);
    canvas.stroke();

    // Fat line left and right
    canvas.moveTo(llx, ury);
    canvas.lineTo(llx, lly);
    canvas.moveTo(urx, ury);
    canvas.lineTo(urx, lly);

    canvas.setLineWidth(0.8f);
    canvas.setColorStroke(Colors.MEDIUM_GRAY);
    canvas.stroke();

    canvas.saveState();
    canvas.restoreState();
}

条形图是表格,其中每个单元格都有一个用于渐变和边框的单元格事件。条形图被添加到第一段代码的 scaleBackground PdfPCell 中,并具有以下 PdfPCellEvents(图表黑色部分的示例):

public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases)
{
    PdfContentByte backgroundCanvas = canvases[PdfPTable.BACKGROUNDCANVAS];
    float llx = rect.getLeft();
    float lly = rect.getBottom();
    float urx = rect.getRight();
    float ury = rect.getTop();

    // Draw background

    // Define shading with direction and color
    PdfShading shading = PdfShading.simpleAxial(this.writer,
                    llx, ury,
                    llx, lly,
                    Colors.BAR_CHART_BLACK_LIGHT, Colors.BAR_CHART_BLACK_DARK);

    PdfShadingPattern pattern = new PdfShadingPattern(shading);
    backgroundCanvas.setShadingFill(pattern);

    // Draw shape with defined shading
    backgroundCanvas.moveTo(llx, ury);
    backgroundCanvas.lineTo(llx, lly);
    backgroundCanvas.lineTo(urx, lly);
    backgroundCanvas.lineTo(urx, ury);
    backgroundCanvas.lineTo(llx, ury);
    backgroundCanvas.fill();

    backgroundCanvas.saveState();
    backgroundCanvas.restoreState();

    // Draw border
    PdfContentByte lineCanvas = canvases[PdfPTable.LINECANVAS];

    float lineWidth = Constants.BORDER_WIDTH_THIN;
    lineCanvas.setLineWidth(lineWidth);
    lineCanvas.moveTo(llx, ury - lineWidth);
    lineCanvas.lineTo(llx, lly);
    lineCanvas.lineTo(urx, lly);
    lineCanvas.lineTo(urx, ury - lineWidth);

    lineCanvas.setColorStroke(BaseColor.BLACK);
    lineCanvas.stroke();

    lineCanvas.saveState();
    lineCanvas.restoreState();
}

最佳答案

这是不同直接内容层的顺序:

  • PdfPtable.BASECANVAS - 放置在此处的任何内容都将位于表格下方。
  • PdfPtable.BACKGROUNDCANVAS - 这是背景所在的图层 绘制。
  • PdfPtable.LINECANVAS - 这是绘制线条的图层。
  • PdfPtable.TEXTCANVAS - 这是文本所在的图层。任何放置的东西 这里将覆盖 table 。

这摘自《iText in Action - 第二版》一书。

您还询问了 saveState()restoreState()Chapter 2 of the iText 7 tutorial对此进行了解释。 :

First we save the current graphics state with the saveState() method, then we change the state and draw whatever lines or shapes we want to draw, finally, we use the restoreState() method to return to the original graphics state. All the changes that we applied after saveState() will be undone. This is especially interesting if you change multiple values (line width, color,...) or when it's difficult to calculate the reverse change (returning to the original coordinate system).

您的代码太长,我无法检查,但我非常怀疑 saveState()/restoreState() 会是您问题的原因。

我会尽量避免嵌套表。使用 colspan 和 rowspan 通常更容易(也更高效)。

如果这不能解决您的问题,请用一句话解释您的问题。

关于java - 有人可以解释一下 iTexts Canvas 绘制顺序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37389019/

相关文章:

java - 在引用管理表 hibernate 的用户表上插入值 1

php - 从 php 生成的 HTML 表生成 PDF

php - MPDF 不显示正确的 CSS

javascript - 检查矢量/Angular 是否与区域相交

java - 如何在 ubuntu 10.04 环境中执行命令(带参数)

java - 如何从 CLI 将 Gradle 任务拆分为纯编译和纯执行任务?

java - 最接近 20 的整数值

javascript - JS Base64 字符串到可下载的 pdf - Edge

javascript - 使用jquery时如何获取HTML5 Canvas ?

c# - 使用 WPF 显示 map