Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8210807

Printing a JTable with a JScrollPane prints table without rows populated

XMLWordPrintable

    • 9
    • b24
    • x86_64
    • windows_10

        ADDITIONAL SYSTEM INFORMATION :
        Reproduced on Windows 10 using Java 11. The table prints fine with the JScrollPane with Java 1.8.0_181

        A DESCRIPTION OF THE PROBLEM :
        A simple JTable doesn't print correctly if the table is contained in a JScrollPane. The same table prints correctly if it's added directly to a JPanel without a JScrollPane.

        Side note: Setting up the JScrollPane to always hide the scroll bars doesn't change the result.

        REGRESSION : Last worked in version 8u181

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        - Run source code below.
        - Print to "Microsoft Print to PDF" printer
        - Open saved pdf
        - Notice printed table doesn't match table visible in program window


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Table printed in pdf should have same number of rows as table appearing in program window
        ACTUAL -
        Table printed in pdf has a complete header but has no row data.

        ---------- BEGIN SOURCE ----------
        import java.awt.*;
        import java.awt.print.*;
        import java.awt.event.WindowEvent;
        import javax.swing.*;
        import javax.swing.table.DefaultTableModel;

        public class TablePrintTest extends JFrame {

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

        // Create table with a JScrollPane
        TestTable testTable = new TestTable(true); // Table row contents don't print

        // Create table without JScrollPane
        //TestTable testTable = new TestTable(false); // Table prints correctly

        add(testTable);
        pack();
        setVisible(true);
        PrintUtilities printerJob = new PrintUtilities(testTable);
        printerJob.print("Test Table Print");
        }

        public class TestTable extends JPanel {

        public TestTable(Boolean useScrollPane) {

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        DefaultTableModel model = new DefaultTableModel();
        model.addColumn("Column 1");
        model.addColumn("Column 2");
        model.addColumn("Column 3");
        model.addColumn("Column 4");

        for (int row=1;row<=5;row++)
        model.addRow(new Object[] {
        "R"+row+" C1", "R"+row+" C2", "R"+row+" C3", "R"+row+" C4" });

        JTable table = new JTable(model);

        if (useScrollPane == true) {
        JScrollPane sp = new JScrollPane(table,
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        sp.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
        add(sp);
        } else {
        add(table.getTableHeader());
        add(table);
        }
        }
        }

        /** A simple utility class that lets you very simply print
        * an arbitrary component. Just pass the component to the
        * PrintUtilities.printComponent. The component you want to
        * print doesn't need a print method and doesn't have to
        * implement any interface or do anything special at all.
        * <P>
        * If you are going to be printing many times, it is marginally more
        * efficient to first do the following:
        * <PRE>
        * PrintUtilities printHelper = new PrintUtilities(theComponent);
        * </PRE>
        * then later do printHelper.print(). But this is a very tiny
        * difference, so in most cases just do the simpler
        * PrintUtilities.printComponent(componentToBePrinted).
        *
        * 7/99 Marty Hall, http://www.apl.jhu.edu/~hall/java/
        * May be freely used or adapted.
        */

        class PrintUtilities implements Printable {
        private Component componentToBePrinted;

        public void printComponent(Component c, String jobname) {
        new PrintUtilities(c).print(jobname);
        }

        public PrintUtilities(Component componentToBePrinted) {
        this.componentToBePrinted = componentToBePrinted;
        }

        public void print(String jobname) {
        PrinterJob printJob = PrinterJob.getPrinterJob();
        PageFormat pf = printJob.defaultPage();
        pf.setOrientation(PageFormat.PORTRAIT);

        // set margins to 1/2"
        Paper p = new Paper();
        p.setImageableArea(36, 36, p.getWidth()-72, p.getHeight()-72);
        pf.setPaper(p);

        printJob.setPrintable(this, pf);
        printJob.setJobName(jobname);

        if (printJob.printDialog()) {
        try {
        printJob.print();
        } catch(PrinterException pe) {
        System.out.println("Error printing: " + pe);
        }
        //componentToBePrinted.setMaximumSize(new SimDimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
        }
        }

        public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
        if (pageIndex > 0) {
        return(NO_SUCH_PAGE);
        } else {
        Graphics2D g2d = (Graphics2D)g;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
        Component c= componentToBePrinted;

        double panelX= c.getWidth();
        double panelY= c.getHeight();
        float imageableX = (float) pageFormat.getImageableWidth()-1;
        float imageableY = (float) pageFormat.getImageableHeight()-1;

        // JPR - Try to do a distortion free scale by scaling both dimensions by the same
        // amount, based on the dimension that needs to be scaled the most
        // orig code - g2d.scale(imageableX/panelX,imageableY/panelY);

        double xscale = imageableX/panelX;
        double yscale = imageableY/panelY;
        double optimalScale;
        if (xscale < yscale)
        optimalScale = xscale;
        else
        optimalScale = yscale;

        if (optimalScale > 1)
        optimalScale = 1; // Don't make the image bigger

        g2d.scale(optimalScale, optimalScale);
        disableDoubleBuffering(c);
        c.paint(g2d);
        enableDoubleBuffering(c);
        return(PAGE_EXISTS);
        }
        }

        /** The speed and quality of printing suffers dramatically if
        * any of the containers have double buffering turned on.
        * So this turns if off globally.
        * @see enableDoubleBuffering
        */
        public void disableDoubleBuffering(Component c) {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(false);
        }

        /** Re-enables double buffering globally. */

        public void enableDoubleBuffering(Component c) {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(true);
        }
        }

        protected void processWindowEvent(WindowEvent e) {
        if (e.getID() == WindowEvent.WINDOW_CLOSING) {
        System.exit(0);
        }
        }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Don't put the table in a JScrollPane. Instead add the table header and table manually to the parent JPanel and print that.

        FREQUENCY : always


          1. TablePrintTest.java
            5 kB
            Pardeep Sharma
          2. results.png
            118 kB
            Pardeep Sharma

              tr Tejesh R
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: