如何将圆角边框应用于表格(单页/多页)? [英] How to apply round corner border to table (single page / multipage)?

查看:72
本文介绍了如何将圆角边框应用于表格(单页/多页)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将圆角边框应用于表格.该表是动态的.这意味着它可以成长为多页或可以容纳在单个页面中.

如果表格在单个页面中,则所有四个角单元的最外角应绘制为圆形. 如果表格长到多页(例如3页),则应将所有四个角单元的最外面的角绘制为对所有3页都是圆形的.

这是我用来实现上述情况的方法.

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.java

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());
        
        // drawing white rectangle over table border in order to hide it.
        aboveCanvas.saveState().setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
        
        // drawing red round rectangle which will be shown as boundary.
        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);
    }
}

现在代码可以正常运行了,但是渲染存在问题.当我在表格边框的顶部绘制白色边框时,它不会完全重叠.同样,外部红色边框在预期区域的外部略微绘制.简而言之,白色矩形和红色矩形彼此不一致.因此,外部边界和单元边界之间存在一些间隙. 我将附加上面代码的生成的输出.要注意到该问题,您可能需要将PDF稍微放大一点.

我对此有一些疑问: 我正在使用顶层画布来获得预期的解决方案.但是,有什么方法可以在渲染时直接修改表格边框?我尝试过

drawContext.getCanvas()
            .saveState()
            .roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();

但是在这种方法中,边框与单元格边界重叠(也需要单元格边界).如果我缺少某些东西可以防止出现此问题,请引导我.

谢谢.

解决方案

getOccupiedAreaBBox方法为您提供边框区域的外部边界框.但是,边框本身具有粗细,默认情况下,当您在PDF中绘制线条时,应在传递外部bbox坐标的同时将线条的中心传递给绘制操作,因此,边距较小且重叠不精确. /p>

要解决此问题,您需要将边框线宽度的一半添加到矩形的所有边缘:

float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);

总而言之,以下定制代码:

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

    // drawing white rectangle over table border in order to hide it.
    aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();

    // drawing red round rectangle which will be shown as boundary.
    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);
}

产生以下视觉结果:

I want to apply round corner border to a table. This table is dynamic. That means it can grow up to multiple pages or can accommodate in single page.

If table comes in single page, then outermost corner of all four corner cells should be drawn as rounded. If table grows up to multiple pages (say 3 pages), then outermost corner of all four corner cells should be drawn as rounded for all 3 pages.

Here is the approach which I am using to implement the above scenario.

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.java

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());
        
        // drawing white rectangle over table border in order to hide it.
        aboveCanvas.saveState().setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
        
        // drawing red round rectangle which will be shown as boundary.
        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);
    }
}

Now the code is working fine as it is supposed to be, but there is an issue with the rendering. when i draw the white border on top of table border it does not overlap it completely. Also the outer red border is drawn slightly outside the expected area. In simple words, white rectangle and red rectangle are not coinciding with each other. So there is some gap coming between the outer border and cell borders. I am attaching the generated output from above code. To notice the issue you might need to zoom the PDF a little bit.

I have some doubts regarding the same: I am using a top canvas to get the expected solution. But is there any approach in which I can modify the table border directly while rendering? I tried

drawContext.getCanvas()
            .saveState()
            .roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();

But in this approach border is overlapped by the cell borders (cell borders are needed as well). If I am missing something to prevent this issue, guide me.

Thanks.

解决方案

The getOccupiedAreaBBox method gives you the outer bounding box of the border area. Borders, however, have thickness on their own, and when you draw lines in PDF by default you should pass the center of the line to the drawing operation, while you are passing the outer bbox coordinates, hence the small margin and imprecise overlap.

To fix the issue, you need to add half of the border line width to all of the edges of your rectangle:

float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);

All in all, the following customized code:

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

    // drawing white rectangle over table border in order to hide it.
    aboveCanvas.saveState().setLineWidth(lineWidth).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();

    // drawing red round rectangle which will be shown as boundary.
    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);
}

Yields the following visual result:

这篇关于如何将圆角边框应用于表格(单页/多页)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆