如何将背景颜色应用于 iText7 中的 table 圆角单元格?
How to apply background color to table cell with round corners in iText7?
我画的 table 是圆角的。 table 是动态的,可以增长到多个页面。现在我想给单元格应用一些背景颜色。每个单元格都可以有自己不同的颜色(不是硬编码的)。但问题是当我将背景颜色应用于角落单元格时,颜色会从角落溢出。角单元的外角是圆的。圆角的实现是使用此方法完成的 .
为了实现这一点,我创建了一个单元格渲染器,它覆盖了 drawBackground() 方法来绘制预期的结果。
CellBackgroundColorRenderer.java
public class CellBackgroundColorRenderer extends CellRenderer {
protected Color color;
protected boolean isColoredBackground;
public CellBackgroundColorRenderer(Cell modelElement, Color color, boolean isColoredBackground) {
super(modelElement);
this.color = color;
this.isColoredBackground = isColoredBackground;
}
@Override
public void drawBackground(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfCanvas canvas = drawContext.getCanvas();
// drawing white rectangle on top any pre existing background color.
canvas.saveState().rectangle(rect).setFillColor(new DeviceRgb(255, 255, 255)).fillStroke().restoreState();
// drawing round corner rectangle for colored bg.
canvas.saveState().roundRectangle(rect.getLeft(),rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).setFillColor(color).fillStroke();
// TODO fill color in those cell corners which are in conjuntion with other cells.
canvas.restoreState();
}
}
TableBorderRenderer.java
public class TableBorderRenderer extends TableRenderer {
private int numberOfColumns;
public TableBorderRenderer(Table modelElement) {
super(modelElement);
numberOfColumns = modelElement.getNumberOfColumns();
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
CellRenderer[] cellRenderers = rows.get(0);
Cell cell = (Cell) cellRenderers[0].getModelElement();
((Cell) cellRenderers[0].getModelElement()).setNextRenderer(new CellBackgroundColorRenderer((Cell) cellRenderers[0].getModelElement(), new DeviceRgb(255, 150, 255), true));
((Cell) cellRenderers[numberOfColumns-1].getModelElement()).setNextRenderer(new CellBackgroundColorRenderer((Cell) cellRenderers[numberOfColumns-1].getModelElement(), new DeviceRgb(255, 150, 255), true));
super.draw(drawContext);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);
aboveCanvas.saveState().setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(new DeviceRgb(255,0,0)).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
}
TableTest.java
public void createPdf(String dest) throws FileNotFoundException {
PdfWriter writer = new PdfWriter(DEST);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc, PageSize.A4, false);
Table table = new Table(3);
for (int i=0; i < 100; i++) {
for (int j=0; j < 3; j++) {
table.addCell(new Cell().add(new Paragraph("Cell content")));
}
}
table.setNextRenderer(new TableBorderRenderer(table));
document.add(table);
document.close();
}
在 TableBorderRenderer 的 draw() 中,我将 CellBackgroundColorRenderer 设置为模态元素,即单元格。现在,我仅为第一行设置 CellBackgroudnColorRenderer。但是当我 运行 程序时,它甚至没有进入 cellRenderer 的 drawBackground()。
我不确定我在这里遗漏了什么。我的方法正确吗?如果没有,你能指导我正确的方法吗?
谢谢。
无需手动为单元格绘制背景颜色 - 功能已经存在:
Table table = new Table(3);
for (int i=0; i < 100; i++) {
for (int j=0; j < 3; j++) {
table.addCell(new Cell()
.setBackgroundColor(ColorConstants.GREEN)
.add(new Paragraph("Cell content")));
}
}
table.setNextRenderer(new TableBorderRenderer(table));
document.add(table);
您唯一需要做的就是剪掉那些绘制在圆角之外的背景。为此,您可以在 TableRenderer
中重载 drawChildren
:
public class TableBorderRenderer extends TableRenderer {
public TableBorderRenderer(Table modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,0,0)).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
@Override
public void drawChildren(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState();
canvas.roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5);
canvas.clip().endPath();
super.drawChildren(drawContext);
canvas.restoreState();
}
}
视觉结果:
我更新了 TableRenderer,因此它使用给定的颜色和给定的半径绘制圆角边框。
using iText.Kernel.Colors;
using iText.Kernel.Pdf.Canvas;
using iText.Layout.Element;
using iText.Layout.Renderer;
using iText.Kernel.Colors;
public class TableBorderRenderer : TableRenderer
{
private const float lineWidth = 0.5f;
private readonly float _radius;
private readonly Color _color;
public TableBorderRenderer(Table modelElement, float radius, Color color = null) : base(modelElement)
{
_radius = radius;
_color = color ?? PdfColors.White;
}
public override IRenderer GetNextRenderer()
{
return new TableBorderRenderer((Table)modelElement, _radius, _color);
}
protected override void DrawBorders(DrawContext drawContext)
{
var rect = GetOccupiedAreaBBox();
var currentPage = drawContext
.GetDocument()
.GetPage(GetOccupiedArea().GetPageNumber());
var aboveCanvas = new PdfCanvas(currentPage.NewContentStreamAfter(), currentPage.GetResources(), drawContext.GetDocument());
rect.ApplyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
aboveCanvas
.SaveState()
.SetLineWidth(lineWidth)
.SetStrokeColor(_color)
.RoundRectangle(rect.GetLeft(), rect.GetBottom(), rect.GetWidth(), rect.GetHeight(), _radius)
.Stroke()
.RestoreState();
base.DrawBorders(drawContext);
}
public override void DrawChildren(DrawContext drawContext)
{
var rect = GetOccupiedAreaBBox();
rect.ApplyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
var canvas = drawContext
.GetCanvas()
.SaveState()
.RoundRectangle(rect.GetLeft(), rect.GetBottom(), rect.GetWidth(), rect.GetHeight(), _radius)
.Clip()
.EndPath();
base.DrawChildren(drawContext);
canvas.RestoreState();
}
}
我画的 table 是圆角的。 table 是动态的,可以增长到多个页面。现在我想给单元格应用一些背景颜色。每个单元格都可以有自己不同的颜色(不是硬编码的)。但问题是当我将背景颜色应用于角落单元格时,颜色会从角落溢出。角单元的外角是圆的。圆角的实现是使用此方法完成的
为了实现这一点,我创建了一个单元格渲染器,它覆盖了 drawBackground() 方法来绘制预期的结果。
CellBackgroundColorRenderer.java
public class CellBackgroundColorRenderer extends CellRenderer {
protected Color color;
protected boolean isColoredBackground;
public CellBackgroundColorRenderer(Cell modelElement, Color color, boolean isColoredBackground) {
super(modelElement);
this.color = color;
this.isColoredBackground = isColoredBackground;
}
@Override
public void drawBackground(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfCanvas canvas = drawContext.getCanvas();
// drawing white rectangle on top any pre existing background color.
canvas.saveState().rectangle(rect).setFillColor(new DeviceRgb(255, 255, 255)).fillStroke().restoreState();
// drawing round corner rectangle for colored bg.
canvas.saveState().roundRectangle(rect.getLeft(),rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).setFillColor(color).fillStroke();
// TODO fill color in those cell corners which are in conjuntion with other cells.
canvas.restoreState();
}
}
TableBorderRenderer.java
public class TableBorderRenderer extends TableRenderer {
private int numberOfColumns;
public TableBorderRenderer(Table modelElement) {
super(modelElement);
numberOfColumns = modelElement.getNumberOfColumns();
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
CellRenderer[] cellRenderers = rows.get(0);
Cell cell = (Cell) cellRenderers[0].getModelElement();
((Cell) cellRenderers[0].getModelElement()).setNextRenderer(new CellBackgroundColorRenderer((Cell) cellRenderers[0].getModelElement(), new DeviceRgb(255, 150, 255), true));
((Cell) cellRenderers[numberOfColumns-1].getModelElement()).setNextRenderer(new CellBackgroundColorRenderer((Cell) cellRenderers[numberOfColumns-1].getModelElement(), new DeviceRgb(255, 150, 255), true));
super.draw(drawContext);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);
aboveCanvas.saveState().setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(new DeviceRgb(255,0,0)).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
}
TableTest.java
public void createPdf(String dest) throws FileNotFoundException {
PdfWriter writer = new PdfWriter(DEST);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc, PageSize.A4, false);
Table table = new Table(3);
for (int i=0; i < 100; i++) {
for (int j=0; j < 3; j++) {
table.addCell(new Cell().add(new Paragraph("Cell content")));
}
}
table.setNextRenderer(new TableBorderRenderer(table));
document.add(table);
document.close();
}
在 TableBorderRenderer 的 draw() 中,我将 CellBackgroundColorRenderer 设置为模态元素,即单元格。现在,我仅为第一行设置 CellBackgroudnColorRenderer。但是当我 运行 程序时,它甚至没有进入 cellRenderer 的 drawBackground()。
我不确定我在这里遗漏了什么。我的方法正确吗?如果没有,你能指导我正确的方法吗?
谢谢。
无需手动为单元格绘制背景颜色 - 功能已经存在:
Table table = new Table(3);
for (int i=0; i < 100; i++) {
for (int j=0; j < 3; j++) {
table.addCell(new Cell()
.setBackgroundColor(ColorConstants.GREEN)
.add(new Paragraph("Cell content")));
}
}
table.setNextRenderer(new TableBorderRenderer(table));
document.add(table);
您唯一需要做的就是剪掉那些绘制在圆角之外的背景。为此,您可以在 TableRenderer
中重载 drawChildren
:
public class TableBorderRenderer extends TableRenderer {
public TableBorderRenderer(Table modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,0,0)).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
@Override
public void drawChildren(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState();
canvas.roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5);
canvas.clip().endPath();
super.drawChildren(drawContext);
canvas.restoreState();
}
}
视觉结果:
我更新了 TableRenderer,因此它使用给定的颜色和给定的半径绘制圆角边框。
using iText.Kernel.Colors;
using iText.Kernel.Pdf.Canvas;
using iText.Layout.Element;
using iText.Layout.Renderer;
using iText.Kernel.Colors;
public class TableBorderRenderer : TableRenderer
{
private const float lineWidth = 0.5f;
private readonly float _radius;
private readonly Color _color;
public TableBorderRenderer(Table modelElement, float radius, Color color = null) : base(modelElement)
{
_radius = radius;
_color = color ?? PdfColors.White;
}
public override IRenderer GetNextRenderer()
{
return new TableBorderRenderer((Table)modelElement, _radius, _color);
}
protected override void DrawBorders(DrawContext drawContext)
{
var rect = GetOccupiedAreaBBox();
var currentPage = drawContext
.GetDocument()
.GetPage(GetOccupiedArea().GetPageNumber());
var aboveCanvas = new PdfCanvas(currentPage.NewContentStreamAfter(), currentPage.GetResources(), drawContext.GetDocument());
rect.ApplyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
aboveCanvas
.SaveState()
.SetLineWidth(lineWidth)
.SetStrokeColor(_color)
.RoundRectangle(rect.GetLeft(), rect.GetBottom(), rect.GetWidth(), rect.GetHeight(), _radius)
.Stroke()
.RestoreState();
base.DrawBorders(drawContext);
}
public override void DrawChildren(DrawContext drawContext)
{
var rect = GetOccupiedAreaBBox();
rect.ApplyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
var canvas = drawContext
.GetCanvas()
.SaveState()
.RoundRectangle(rect.GetLeft(), rect.GetBottom(), rect.GetWidth(), rect.GetHeight(), _radius)
.Clip()
.EndPath();
base.DrawChildren(drawContext);
canvas.RestoreState();
}
}