JTable 打印。如何以编程方式设置分页符?

JTable Printing. How to set page breaks programmatically?

我正在尝试找到一种以编程方式设置分页符以打印出 JTable 的方法。

例如,我有一个 table 大约有 150 行,如下所示:


行号Data1 Data2 Data3 …等
1 a b c d
1 a b c d
1 a b c d
2 a b c d
2 a b c d
3 a b c d
3 a b c d
3 a b c d
3 a b c d
4 a b c d
5 a b c d
5 a b c d
5 a b c d
…等 …等…等…等…等

我需要想办法在行号改变时开始打印新的一页。

我找到了 printing selected rows 的方法,到目前为止已经修改它以循环遍历我的 table 将行添加到临时打印模型,然后在重置之前调用 print() 方法进行打印临时变量。但是,这意味着我可能调用 print() 10 次,每个行号调用一次,这是一个 unacceptable 解决方案。完成当前漏洞解决方案的代码如下:

btnPrint.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try {
                int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
                WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
                for (int i = 0; i < table.getRowCount(); i++) {
                    if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
                        System.out.println(table.getValueAt(i, -1));
                        printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
                    } else {
                        wrappingLineNumber = (Integer) table.getValueAt(i, 0);
                        // if not the same, i.e., value changed
                        JTable toPrint = new JTable(printModel);
                        toPrint.setSize(toPrint.getPreferredSize());
                        JTableHeader tableHeader = toPrint.getTableHeader();
                        tableHeader.setSize(tableHeader.getPreferredSize());
                        toPrint.print(JTable.PrintMode.FIT_WIDTH);
                        printModel.removeAll();
                        printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
                    }
                }
                System.out.println("success printing");
            } catch (PrinterException pe) {
                System.out.println("printing failed");
                pe.printStackTrace();
            }
        };
    });

任何人都可以提供更好的解决方案,只要行号列中的值发生变化,就会在新页面上开始打印吗?

非常感谢您提供的任何帮助!

经过进一步的研究和思考,我意识到可以创建 sub-tables/temporary tables 只保存与每条换行相关的信息。接下来的问题是如何将多个 JTable 作为一个打印作业进行打印。已提出并回答了此问题的变体 here and particularly here。根据第二个 link 中提供的信息,我想出的解决方案如下:

解决方案使用 Durandal 在上面的 link 2 中提供的未更改的 PrintableWrapper,包含在此处仅供参考 "to spare us the hassle of iterating over each page":

public class PrintableWrapper implements Printable {
private Printable delegate;
private int offset;

public PrintableWrapper(Printable delegate, int offset) {
    this.offset = offset;
    this.delegate = delegate;
}

@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
    return delegate.print(graphics, pageFormat, pageIndex-offset);
}}

解决方案还利用相同 link 中未更改的 kleopatra / Durandal 代码来获取每个 table 所需的页数:

public int getNumberOfPages(Printable delegate, PageFormat pageFormat) throws PrinterException {
    Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
    int numPages = 0;
    while (true) {
        int result = delegate.print(g, pageFormat, numPages);
        if (result == Printable.PAGE_EXISTS) {
            ++numPages;
        } else {
            break;
        }
    }

    return numPages;
}

据此,解决方案是创建 PrinterJob、Book 和临时 JTable。然后把临时的table加到书里,用上面的class和方法。最后打印这本书。此解决方案的当前代码可以在下面找到,代码中包含解释性注释:

btnPrint.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    try {
                        //Code revised from 
                        // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
                        PrinterJob printerJob = PrinterJob.getPrinterJob();

                        //Set 1/4 " margins and orientation
                        PageFormat pf = printerJob.defaultPage();
                        pf.setOrientation(PageFormat.LANDSCAPE);
                        Paper paper = new Paper();
                        //double margin = 36; // half inch
                        double margin = 18; // quarter inch
                        paper.setImageableArea(margin, margin, paper.getWidth() - margin * 2, paper.getHeight() - margin * 2);
                        pf.setPaper(paper);

                        Book bookToPrint = new Book();
                        // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
                        //Code revised from 

                        // List to store temporary tables to print
                        List<JTable> tablesToPrint = new ArrayList<JTable>();

                        // create temporary print tables by wrapping line number
                        int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
                        WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
                        for (int i = 0; i < table.getRowCount(); i++) {
                            if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
                                // add wrapping sheet row to print model
                                printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
                            } else {
                                // if not the same, i.e., value changed
                                // create a new table
                                JTable toPrint = new JTable(printModel);

                                // set size of table as if size isn't set the table contents aren't printed
                                toPrint.setSize(toPrint.getPreferredSize());
                                // reduce row height for printing
                                toPrint.setRowHeight(16);
                                // add table to print to list of tables to be printed
                                tablesToPrint.add(toPrint);

                                // create a new print model for next table to be printed
                                printModel = new WrappingSheetsTableModel();
                                // add first new wrapping sheet row to print model
                                printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
                                // increment the wrapping line number
                                wrappingLineNumber = (Integer) table.getValueAt(i, 0);
                            }
                        }
                        // add in last table to print
                        JTable toPrint = new JTable(printModel);
                        // set size of table as if size isn't set the table contents aren't printed
                        toPrint.setSize(toPrint.getPreferredSize());
                        // reduce row height for printing
                        toPrint.setRowHeight(16);

                        // add last table to print to list of tables to be printed
                        tablesToPrint.add(toPrint);

                        // add each table to be printed to book for printing
                        int totalPages = 0;
                        for (JTable table : tablesToPrint) {
                            // get the table header information from table
                            JTableHeader tableHeader = table.getTableHeader();
                            // set size so that table header will be visible
                            tableHeader.setSize(tableHeader.getPreferredSize());

                            // get number of pages in printable table
                            int pages = getNumberOfPages(table.getPrintable(PrintMode.FIT_WIDTH, null, null), pf);

                            // create temporary printable to add to book
                            Printable p = table.getPrintable(PrintMode.FIT_WIDTH, null, null);
                            // add printable to book using printable wrapper
                            // p - printable, totalPages - total pages, pf - page format, pages - num pages to add
                            bookToPrint.append(new PrintableWrapper(p, totalPages), pf, pages);

                            // increase total pages count
                            totalPages += pages;
                        }

                        //Checks for page count:
                        //System.out.println(totalPages);
                        //System.out.println(bookToPrint.getNumberOfPages());

                        // Queries document for the number of pages 
                        // and the PageFormat 
                        // and Printable 
                        // for each page held in the Pageable instance, document.
                        printerJob.setPageable(bookToPrint);

                        // show print dialog
                        // - printer selection and pages to print work
                        // - changing from e.g. landscape to portrait does not work currently
                        if(printerJob.printDialog()) printerJob.print();

                        System.out.println("success printing X");
                    } catch (PrinterException pe) {
                        System.out.println("printing failed");
                        pe.printStackTrace();
                    }
                };
            });

每个页面现在只包含那些具有相同换行号的行,并且当换行号改变时开始新的页面。 (仍然需要对 PageFormat 和 PrintDialog 进行更多研究,因为打印对话框中页面方向的更改目前不会影响最终的打印布局)。