【问题标题】:JTable Printing. How to set page breaks programmatically?JTable 打印。如何以编程方式设置分页符?
【发布时间】:2015-06-08 13:03:03
【问题描述】:

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

例如,我有一个大约有 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 的方法,到目前为止,我已经修改它以循环遍历我的表,将行添加到临时打印模型,然后在重置临时变量之前调用 print() 方法进行打印。但是,这意味着我可能会调用 print() 10 次,每个行号一次,这是一个不可接受的解决方案。完成当前有缺陷的解决方案的代码如下:

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

谁能提供一个更好的解决方案,只要行号列中的值发生变化,就会在新页面上开始打印?

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

【问题讨论】:

  • 是在一张纸的末尾,一行的一半会打印在一张纸上,另一半会打印在下一张纸上吗?
  • 我还没有遇到过这个问题。不,问题是基本 print() 决定何时发生分页符,但在这种情况下,我想根据表中的行号列来控制它。 (因此所有第 1 行的条目都在一个页面上,所有第 2 行的条目都在下一页上,依此类推)。

标签: java swing printing jtable


【解决方案1】:

经过进一步的研究和思考,我意识到可以创建子表/临时表,只保存与每条包装线相关的信息。那么问题是如何将多个 JTable 打印为一个打印作业。这个问题的变体已经被询问和回答here,特别是here。根据第二个链接中提供的信息,我想出的解决方案如下:

解决方案使用了 Durandal 在上面的链接 2 中提供的未更改的 PrintableWrapper,此处包含的信息是为了“免去我们遍历每个页面的麻烦”:

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

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

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 和 Temporary JTables。然后使用上面的类和方法将临时表添加到书中。最后打印这本书。此解决方案的当前代码可以在下面找到,代码中包含解释性 cmets:

btnPrint.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    try {
                        //Code revised from https://stackoverflow.com/questions/14775753/printing-multiple-jtables-as-one-job-book-object-only-prints-1st-table?rq=1
                        // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
                        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 https://stackoverflow.com/questions/14775753/printing-multiple-jtables-as-one-job-book-object-only-prints-1st-table?rq=1

                        // 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 进行更多研究,因为打印对话框中页面方向的更改目前不会影响最终的打印布局。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多