Printing a JPanel with Scrollable Jtable On it [closed]

There is a reason why I suggest using something like Jasper Reports, this has taken the better part of two days to nut out. JTable doesn’t like been treated this way.

Basically, there is the “UI view”, which shows the data on the screen and the “print view” which used to generate the print out.

UI View…

UI View

Print view…

Print View

This example, on A4 paper, will generate 22 pages…

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.DialogTypeSelection;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            DefaultTableModel model = new DefaultTableModel();
            int columnCount = 10;
            for (int index = 0; index < columnCount; index++) {
                model.addColumn((char) ('A' + index));
            }
            for (int row = 0; row < 1000; row++) {
                Object[] data = new Object[columnCount];
                for (int col = 0; col < columnCount; col++) {
                    data[col] = row + "x" + col;
                }
                model.addRow(data);
            }

            setLayout(new BorderLayout());
            JTable table = new JTable(model);
            add(new JScrollPane(table));
            JButton print = new JButton("Print");
            add(print, BorderLayout.SOUTH);
            print.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        PrintPane printPane = new PrintPane(model);

                        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
                        aset.add(MediaSizeName.ISO_A4);
                        aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
                        aset.add(DialogTypeSelection.NATIVE);

                        PrinterJob pj = PrinterJob.getPrinterJob();
                        pj.setPrintable(printPane);

                        PageFormat pf = pj.defaultPage();
                        pf.setOrientation(PageFormat.LANDSCAPE);

                        if (pj.printDialog(aset)) {
                            try {
                                pj.print(aset);
                            } catch (PrinterException ex) {
                                ex.printStackTrace();
                            }
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }

                }
            });
        }

    }

    public class PrintPane extends JPanel implements Printable {

        private JTable table;

        public PrintPane(TableModel model) throws IOException {
            setLayout(new GridBagLayout());
            BufferedImage logo = ImageIO.read(...);
            JLabel header = new JLabel("Honest Bob's Used Ponys", new ImageIcon(logo), JLabel.LEFT);
            header.setFont(header.getFont().deriveFont(Font.BOLD, 24f));
            header.setVerticalAlignment(JLabel.TOP);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            add(header, gbc);

            table = new JTable(model);
            JTableHeader tableHeader = table.getTableHeader();
            gbc.gridy++;
            add(tableHeader, gbc);

            gbc.gridy++;
            gbc.fill = GridBagConstraints.BOTH;
            add(new JTable(model), gbc);
            setBackground(Color.WHITE);
        }

        private int lastPage = 0;
        private double yOffset;

        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            int result = NO_SUCH_PAGE;

            String name = "I be mighty!";
            String page = Integer.toString(pageIndex);

            double height = pageFormat.getImageableHeight();
            double width = pageFormat.getImageableWidth();

            System.out.println("Page = " + width + "x" + height);

            JTableHeader tableHeader = table.getTableHeader();
            Dimension size = tableHeader.getPreferredSize();
            tableHeader.setPreferredSize(new Dimension((int) width, size.height));
            tableHeader.setSize(table.getPreferredSize());

            size = table.getPreferredSize();
            table.setPreferredSize(new Dimension((int) width, size.height));
            table.setSize(table.getPreferredSize());

            size = getPreferredSize();
            setSize((int)width, size.height);
            invalidate();
            doLayout();

            table.doLayout();
            tableHeader.doLayout();

            if (lastPage != pageIndex) {
                lastPage = pageIndex;
                yOffset = height * pageIndex;
                if (yOffset > getHeight()) {
                    yOffset = -1;
                }
            }

            if (yOffset >= 0) {
                Graphics2D g2d = (Graphics2D) graphics.create();

                g2d.translate((int) pageFormat.getImageableX(),
                        (int) pageFormat.getImageableY());

                g2d.translate(0, -yOffset);
                printAll(g2d);

                g2d.dispose();

                result = PAGE_EXISTS;
                System.out.println("Print page " + pageIndex);
            }
            return result;
        }

    }
}

There is one significant problem, the fact that a row might be split over two pages. This would require you to be able to calculate the number of rows which would fit onto the page and clip the Graphics accordingly, but I’ll leave that to you to figure out

Leave a Comment