You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Printable多页打印异常:第二页空白问题求助

解决Java Printable多页打印第二页空白的问题

我来帮你搞定这个第二页空白的问题,核心问题出在你对全局任务索引i的处理上——既没结合页码计算页内的相对位置,还错误地用全局索引计算绘制坐标,导致第二页的内容要么没进入绘制分支,要么画到了页面可见区域之外。

问题拆解

  1. 全局索引未转换为页内相对索引:你原来的if ((i < 9) || ((i>=3*9) && (i<4*9)))这类判断,只对第一页的任务(i=0~26)有效。第二页的任务i=27~53完全不满足这些条件,自然不会执行任何绘制代码。
  2. 坐标计算错误:就算第二页的任务进入了分支,你用i * 90计算y坐标,i=27时y值会达到10+27*90=2440,远远超出了打印页面的可打印区域,内容根本看不到。

修复后的代码

我调整了逻辑,先把全局索引转换为当前页内的相对索引,再基于这个索引计算任务在页面的列和行位置,确保每一页的内容都能正确绘制:

public class Printer implements Printable { 
    private ArrayList<Task> dataTasks; 
    private ArrayList<Tag> dataTags; 
    private int tasksPerPage = 27; 
    // 每页3列,每列9个任务
    private final int tasksPerCol = 9;
    // 三列的x偏移量
    private final int[] colXOffsets = {10, 202, 392};

    public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { 
        // 计算当前页的起始和结束索引
        int startIndex = pageIndex * tasksPerPage;
        if (startIndex >= dataTasks.size()) { 
            return NO_SUCH_PAGE; 
        }
        int endIndex = Math.min(startIndex + tasksPerPage, dataTasks.size());

        Graphics2D g2d = (Graphics2D) g; 
        g2d.translate(pf.getImageableX(), pf.getImageableY()); 
        Font titleFont = new Font("Courier New", Font.PLAIN, 12); 
        g2d.setFont(titleFont); 

        for (int i = startIndex; i < endIndex; i++){ 
            // 计算当前任务在当前页内的相对索引(0~26)
            int pageRelativeIndex = i - startIndex;
            // 计算属于哪一列(0=第一列,1=第二列,2=第三列)
            int col = pageRelativeIndex / tasksPerCol;
            // 计算在当前列的第几行(0~8)
            int rowInCol = pageRelativeIndex % tasksPerCol;
            // 当前列的x坐标
            int x = colXOffsets[col];
            // 当前任务的基础y坐标
            int baseY = 10 + rowInCol * 90;

            // 绘制任务基本信息
            g.drawString("Task: " + dataTasks.get(i).getName(), x, baseY); 
            g.drawString("Created: " + dataTasks.get(i).getCreationDate().toString(true,false), x, baseY + 12); 
            g.drawString("Deadline: " + dataTasks.get(i).getDeadline().toString(true,true), x, baseY + 24); 
            g.drawString("Compl.: " + dataTasks.get(i).getCompletionDate().toString(true,true), x, baseY + 36); 

            // 绘制标签
            List<Integer> tagIds = dataTasks.get(i).gettagIdList();
            if (tagIds.isEmpty()){ 
                g.drawString("Tags: ", x, baseY + 48); 
            } else { 
                int tagY = baseY + 48;
                for (int j = 0; j < tagIds.size(); j++) { 
                    for (int k = 0; k < dataTags.size(); k++) { 
                        if (tagIds.get(j) == dataTags.get(k).getId()){ 
                            if (j == 0){ 
                                g.drawString("Tags: " + dataTags.get(k).getName(), x, tagY); 
                            } else { 
                                g.drawString(" " + dataTags.get(k).getName(), x, tagY); 
                            }
                            tagY += 10; // 下一个标签往下偏移10
                            break; // 找到对应标签后跳出内层循环
                        } 
                    } 
                } 
            } 
        } 
        return PAGE_EXISTS; 
    } 
}

关键修改点

  • 页内相对索引:通过pageRelativeIndex = i - startIndex把全局索引转换成当前页的0~26范围,确保每一页的任务位置计算逻辑一致。
  • 行列划分:用col = pageRelativeIndex / 9和rowInCol = pageRelativeIndex % 9清晰划分任务在页面的列和行,替代原来复杂且错误的全局索引判断。
  • 坐标统一计算:用baseY = 10 + rowInCol * 90确保每列的任务从上到下依次排列,不会出现第二页y坐标溢出的问题。
  • 优化标签循环:添加break减少不必要的循环,同时统一标签的y偏移逻辑。

这样修改后,不管是第1页还是第N页,任务都会按照3行9列的布局正确绘制在页面可见区域内,不会再出现空白页的问题。

内容的提问来源于stack exchange,提问作者Nikola Petkovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:30:32