简体   繁体   English

如何在iText7中将背景颜色应用于带有圆角的表格单元格?

[英]How to apply background color to table cell with round corners in iText7?

I am drawing the table with round corners.我正在画圆角的桌子。 The table is dynamic and can grow to multiple pages.该表是动态的,可以增长到多个页面。 Now I want to apply some background color to cells.现在我想为单元格应用一些背景颜色。 Each cell can have its own different color (not hard coded).每个单元格可以有自己不同的颜色(非硬编码)。 But the issue is when I apply background color to corner cells, the color spills out from corners.但问题是当我将背景颜色应用于角落单元格时,颜色会从角落溢出。 The corner cells have their outer corners round.角单元的外角是圆形的。 The implementation of round corner is done using this method https://stackoverflow.com/a/62764267/13446374 .圆角的实现是使用这种方法https://stackoverflow.com/a/62764267/13446374完成的。

For implementing this I created a cell renderer which overrides the drawBackground() method to draw the expected results.为了实现这一点,我创建了一个单元格渲染器,它覆盖了 drawBackground() 方法来绘制预期的结果。

CellBackgroundColorRenderer.java 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 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表Test.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();
        
}

In draw() of TableBorderRenderer I am setting the CellBackgroundColorRenderer to the modal element, ie cell.在 TableBorderRenderer 的 draw() 中,我将 CellBackgroundColorRenderer 设置为模态元素,即单元格。 For now, I am setting the CellBackgroudnColorRenderer for first row only.现在,我只为第一行设置 CellBackgroudnColorRenderer。 But when I run the program, it doesn't even go in that drawBackground() of cellRenderer.但是当我运行程序时,cellRenderer的drawBackground()中甚至没有go。

I am not sure what I am missing here.我不确定我在这里缺少什么。 Is my approach correct?我的方法正确吗? If not, can you guide me with the correct approach?如果没有,你能用正确的方法指导我吗?

Thanks.谢谢。

No need to manually draw the background color for cells - the functionality is already there:无需手动绘制单元格的背景颜色 - 该功能已经存在:

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);

The only thing you need to do is to clip those backgrounds that are drawn outside of the rounded corners.您唯一需要做的就是剪裁那些在圆角之外绘制的背景。 You can overload drawChildren in TableRenderer for that:为此,您可以在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();
    }
}

Visual result:视觉结果:

结果

I updated the TableRenderer, so it draws the rounded border with the given color and the given radius.我更新了 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM