jjzjj

android - PDFJet-开源 : How to set multiline text inside Cell object

coder 2023-12-27 原文

我使用 PDFJet-Open-Source 库构建 pdf。所以,我有几个问题:

1) 如何在单元格中放置多行文本?

问题描述: 目前我面临无法将多行文本放入 Cell 对象的问题。我试过像 "text1\n text2..." 这样的设置文本,但它没有任何效果。遗憾的是,开源版本没有 TextColumn 和 Paragraph 类。

2) 什么是 CompositeTextLine 以及如何使用它?

问题描述:可能是我的想象有误,但我尝试了以下操作:

...
CompositeTextLine ctl = new CompositTextLine(0,0);
ctl.addComponent(new TextLine(f1,"MyText1"));
ctl.addComponent(new TextLine(f1,"MyText2"));
ctl.addComponent(new TextLine(f1,"MyText3"));
Cell cell = new Cell(f1);
cell.setCompositeTextLine(ctl);
...

我希望在 Cell 中看到几行,但我什么也没观察到。此外,如果我添加 table.wrapAroundCellText() 行,我会遇到 NullPointerException。如果我调用 ctl.drawOn(page),我只会观察到:“MyText1 MyText2 MyText3”而没有换行。

更新:我发现了 TextBox 类,因此,如果我写:

TextBox textbox = new TextBox(f1);
textbox.setText("First Line \n Second Line");
textbox.drawOn(page);

它将构建我想要的:

First Line
Second Line

但我仍然对 (1) 的可能性和 (2) 的描述以及其中的一些变体感兴趣,例如“如何在 Cell 中设置 TextBox(或图像等),而不仅仅是单行?”

最后一个,请问有没有大佬指点一下Java或者C++中“文本对齐”算法的实现。

最佳答案

我可以解决同样的问题,我最终扩展了 Cell,并使用了 WordUtils来自 apache commons lang3 :

public class MultilineCell extends Cell {

    private final int characterCount;

    public MultilineCell(Font font, String content, int characterCount) {
        super(font, content);
        this.characterCount = characterCount;
    }

    @Override
    public String getText() {
        return WrapUtil.wrap(super.getText(), this.characterCount);
    }

    @Override
    public float getHeight() {
        float height = this.font.getBodyHeight();

        String text = getText();
        if (text != null) {
            String[] wrappedTexts = text.split(System.getProperty("line.separator"));

            if (wrappedTexts.length > 1) {
                return (height * wrappedTexts.length) + this.top_padding + this.bottom_padding;
            }
        }
        return height + this.top_padding + this.bottom_padding;
    }

    @Override
    protected void paint(Page page, float x, float y, float w, float h) throws Exception {
        page.setPenColor(this.getPenColor());
        page.setPenWidth(this.lineWidth);

        drawBorders(page, x, y, w, h);
        drawText(page, x, y, w);
    }

    private void drawBorders(
            Page page,
            float x,
            float y,
            float cell_w,
            float cell_h) throws Exception {

        if (getBorder(Border.TOP) &&
                getBorder(Border.BOTTOM) &&
                getBorder(Border.LEFT) &&
                getBorder(Border.RIGHT)) {
            page.drawRect(x, y, cell_w, cell_h);
        }
        else {
            if (getBorder(Border.TOP)) {
                page.moveTo(x, y);
                page.lineTo(x + cell_w, y);
                page.strokePath();
            }
            if (getBorder(Border.BOTTOM)) {
                page.moveTo(x, y + cell_h);
                page.lineTo(x + cell_w, y + cell_h);
                page.strokePath();
            }
            if (getBorder(Border.LEFT)) {
                page.moveTo(x, y);
                page.lineTo(x, y + cell_h);
                page.strokePath();
            }
            if (getBorder(Border.RIGHT)) {
                page.moveTo(x + cell_w, y);
                page.lineTo(x + cell_w, y + cell_h);
                page.strokePath();
            }
        }

    }

    private void drawText(
            Page page,
            float x,
            float y,
            float cell_w) throws IOException {

        String wrappedText = WrapUtil.wrap(super.getText(), this.characterCount);
        String[] lines = wrappedText.split(System.getProperty("line.separator"));

        float x_text = x + this.left_padding;
        float y_text = y + this.font.getAscent() + this.top_padding;

        for (String line : lines) {
            page.drawString(this.font, line, x_text, y_text);
            y_text += this.font.getBodyHeight();
        }
    }
}

您可以像使用 Cell 一样实例化和添加 MultilineCell:

List<Cell> rowCells = new ArrayList<Cell>();
rowCells.add(new MultilineCell(font, c.getString(reasonIdx), 42));

我知道扩展不是一个好的解决方案,复制 drawBorders() 更糟糕,但在这种情况下,如果您不想 fork PDFJet,这是唯一的解决方案。

但这会破坏 autoAdjustColumnWidths:宽度是根据整个文本而不是最长的行计算的。因此,如果您打算使用此方法,子类 Table,派生 PDFJet,或仅提取此方法(后者的唯一缺点是我无法解决单元格填充问题):

/**
 * Auto adjusts the widths of all columns so that they are just wide enough to hold the text without truncation.
 */
private static void autoAdjustColumnWidths(List<List<Cell>> tableData) {
    // Find the maximum text width for each column
    float[] max_col_widths = new float[tableData.get(0).size()];
    for (int i = 0; i < tableData.size(); i++) {
        List<Cell> row = tableData.get(i);
        for (int j = 0; j < row.size(); j++) {
            Cell cell = row.get(j);
            if (cell.getColSpan() == 1) {
                float cellWidth = 0f;
                if (cell.getImage() != null) {
                    cellWidth = cell.getImage().getWidth();
                }
                if (cell.getText() != null) {
                    // Is this a multiline cell? If so, measure the widest line
                    if (cell.getText().contains(MultilineCell.NEW_LINE)) {
                        String[] lines = cell.getText().split(MultilineCell.NEW_LINE);
                        for (String line : lines) {
                            if (cell.getFont().stringWidth(cell.getFallbackFont(), line) > cellWidth) {
                                cellWidth = cell.getFont().stringWidth(cell.getFallbackFont(), line);
                            }
                        }
                    }
                    // Standard (single-line) cell, measure whole text
                    else {
                        if (cell.getFont().stringWidth(cell.getFallbackFont(), cell.getText()) > cellWidth) {
                            cellWidth = cell.getFont().stringWidth(cell.getFallbackFont(), cell.getText());
                        }
                    }
                }
                cell.setWidth(cellWidth + 2f /*cell.left_padding*/ + 2f/*cell.right_padding*/);
                if (max_col_widths[j] == 0f ||
                        cell.getWidth() > max_col_widths[j]) {
                    max_col_widths[j] = cell.getWidth();
                }
            }
        }
    }

    for (int i = 0; i < tableData.size(); i++) {
        List<Cell> row = tableData.get(i);
        for (int j = 0; j < row.size(); j++) {
            Cell cell = row.get(j);
            cell.setWidth(max_col_widths[j]);
        }
    }
}

PDFJet 是一个有趣的库,顺便说一句: protected 字段,所有其他方法都会抛出异常,并且这些类绝对不是为扩展而设计的,即使没有最终的。

关于android - PDFJet-开源 : How to set multiline text inside Cell object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22970547/

有关android - PDFJet-开源 : How to set multiline text inside Cell object的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. python - 开源 Twitter 克隆(在 Ruby/Python 中) - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭6年前。Improvethisquestion是否有任何用Ruby或Python编写的生产就绪的开源Twitter克隆?我对功能丰富的实现更感兴趣,而不仅仅是简单的Twitter消息(例如:API、FBconnect、通知等)谢谢!

  3. Gradle 自动化构建开源工具 - 2

    文章目录写在前面1、下载与安装(windows)1.1、idea中配置gradle2、基础知识(Gradle6.9为例)2.1、Gradle脚本语法2.1.1、dependsOn2.1.2、创建动态任务2.1.3、增加任务行为2.1.4、参数2.1.5、Ant任务2.1.6、方法2.1.7、默认任务2.1.6、依赖任务的不同输出3、java项目中使用3.1、在已有项目中构建gradle3.2、在新建项目时构建gradle(idea)3.3、gradle项目目录结构3.4、build.gradle3.4.1、plugins3.4.2、repositories3.4.3、dependencies3

  4. 停车系统源码-基于springboot+uniapp开源项目 - 2

    Iparking停车收费管理系统-可商用介绍Iparking是一款基于springBoot的停车收费管理系统,支持封闭车场和路边车场,支持微信支付宝多种支付渠道,支持多种硬件,涵盖了停车场管理系统的所有基础功能。技术栈Springboot,MybatisPlus,Beetl,Mysql,Redis,RabbitMQ,UniApp功能云端功能序号模块功能描述1系统管理菜单管理配置系统菜单2系统管理组织管理管理组织机构3系统管理角色管理配置系统角色,包含数据权限和功能权限配置4系统管理用户管理管理后台用户5系统管理租户管理多租户管理6系统管理公众号配置租户公众号配置7系统管理操作日志审计日志8系统

  5. ruby-on-rails - 有没有很好的引用(开源)Rails NoSQL应用程序? - 2

    我有兴趣了解使用nosql将如何影响rails应用程序的架构/设计/代码。有人知道使用nosql持久性的开源rails应用程序的一个好例子吗?谢谢 最佳答案 看看这些项目:卡桑德拉用法atDigg。卡桑德拉用法atTwitter。Friendly用法atFetLife(nsfw)。最后,MyNoSQL是一个提供nosql相关信息的好网站。 关于ruby-on-rails-有没有很好的引用(开源)RailsNoSQL应用程序?,我们在StackOverflow上找到一个类似的问题:

  6. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  7. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

  8. AiBote 2022 新研发的自动化框架,支持 Android 和 Windows 系统。速度非常快 - 2

    Ai-Bot基于流行的Node.js和JavaScript语言的一款新自动化框架,支持Windows和Android自动化。1、Windowsxpath元素定位算法支持支持Windows应用、.NET、WPF、Qt、Java和Electron客户端程序和ie、edgechrome浏览器2、Android支持原生APP和H5界面,元素定位速度是appium十倍,无线远程自动化操作多台安卓设备3、基于opencv图色算法,支持找图和多点找色,1080*2340全分辨率找图50MS以内4、内置免费OCR人工智能技术,无限制获取图片文字和找字功能。5、框架协议开源,除官方node.jsSDK外,用户可

  9. Android Gradle 7.1+新版本依赖变化 - 2

    前一段时间由于工作需要把可爱的小雪狐舍弃了,找到了小蜜蜂。但是新版本的小蜜蜂出现了很多和旧版本不一样的位置。1.功能位置迁移,原来在工程build.gradle的buildscript和allprojects移动至setting.gradle并改名为pluginManagement和dependencyResolutionManagement。里面的东西依旧可以按照原来的copy过来。pluginManagement{repositories{gradlePluginPortal()google()mavenCentral()}}dependencyResolutionManagement{r

  10. ruby - Ruboto 的最佳教程(适用于 Android 的 ruby​​)? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion我几乎用完了Ruby,但现在想试试Ruboto,android上的ruby​​。谷歌未能给我足够的(几乎没有结果)。所以任何人都可以分享一些关于Ruboto的教程。

随机推荐