我尝试在 iText 中绘制一些嵌套表格,因为我认为这是定位所有内容的最简单方法。
所以我在另一个表中有多个表,它们都有背景颜色和/或笔画(通过 PdfPCellEvents)。不幸的是,外表的笔划与内表的背景重叠。
我认为这是由于应用顺序错误或 PdfPCellEvents 中的一些错误设置 saveState
或 restoreState
造成的。
谁能向我解释一下 saveState
和 restoreState
的正确用法,并提示我如何正确应用背景和描边?
这是我添加条纹背景单元格的代码:
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 therestoreState()
method to return to the original graphics state. All the changes that we applied aftersaveState()
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/