0

I want to print a table with Java but my class that implements the Printable class print one page and when my table is big, break it into two pages and just prints the last page. I won't print one page if there is more pages print all of them.

this is my TablePrintable Class:

class TablePrintable implements Printable {

/** The table to print. */
private JTable table;

/** For quick reference to the table's header. */
private JTableHeader header;

/** For quick reference to the table's column model. */
private TableColumnModel colModel;

/** To save multiple calculations of total column width. */
private int totalColWidth;

/** The printing mode of this printable. */
private JTable.PrintMode printMode;

/** Provides the header text for the table. */
private MessageFormat headerFormat;

/** Provides the footer text for the table. */
private MessageFormat footerFormat;

/** The most recent page index asked to print. */
private int last = -1;

/** The next row to print. */
private int row = 0;

/** The next column to print. */
private int col = 0;

/** Used to store an area of the table to be printed. */
private final Rectangle clip = new Rectangle(0, 0, 0, 0);

/** Used to store an area of the table's header to be printed. */
private final Rectangle hclip = new Rectangle(0, 0, 0, 0);

/** Saves the creation of multiple rectangles. */
private final Rectangle tempRect = new Rectangle(0, 0, 0, 0);

/** Vertical space to leave between table and header/footer text. */
private static final int H_F_SPACE = 15;

/** Font size for the header text. */
private static final float HEADER_FONT_SIZE = 14.0f;

/** Font size for the footer text. */
private static final float FOOTER_FONT_SIZE = 10.0f;

/** The font to use in rendering header text. */
private Font headerFont;

/** The font to use in rendering footer text. */
private Font footerFont;

/**
 * Create a new <code>TablePrintable</code> for the given
 * <code>JTable</code>. Header and footer text can be specified using the
 * two <code>MessageFormat</code> parameters. When called upon to provide a
 * String, each format is given the current page number.
 * 
 * @param table
 *            the table to print
 * @param printMode
 *            the printing mode for this printable
 * @param headerFormat
 *            a <code>MessageFormat</code> specifying the text to be used in
 *            printing a header, or null for none
 * @param footerFormat
 *            a <code>MessageFormat</code> specifying the text to be used in
 *            printing a footer, or null for none
 * @throws IllegalArgumentException
 *             if passed an invalid print mode
 */
    public TablePrintable(JTable table, JTable.PrintMode printMode, 
     MessageFormat headerFormat,
        MessageFormat footerFormat) {

    this.table = table;

    header = table.getTableHeader();
    colModel = table.getColumnModel();
    totalColWidth = colModel.getTotalColumnWidth();

    if (header != null) {
        // the header clip height can be set once since it's unchanging
        hclip.height = header.getHeight();
    }

    this.printMode = printMode;

    this.headerFormat = headerFormat;
    this.footerFormat = footerFormat;

    // derive the header and footer font from the table's font
    headerFont = table.getFont().deriveFont(Font.BOLD, HEADER_FONT_SIZE);
    footerFont = table.getFont().deriveFont(Font.PLAIN, FOOTER_FONT_SIZE);
}

/**
 * Prints the specified page of the table into the given {@link Graphics}
 * context, in the specified format.
 * 
 * @param graphics
 *            the context into which the page is drawn
 * @param pageFormat
 *            the size and orientation of the page being drawn
 * @param pageIndex
 *            the zero based index of the page to be drawn
 * @return PAGE_EXISTS if the page is rendered successfully, or NO_SUCH_PAGE
 *         if a non-existent page index is specified
 * @throws PrinterException
 *             if an error causes printing to be aborted
 */
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) 
throws PrinterException {

    // for easy access to these values
    final int imgWidth = (int) pageFormat.getImageableWidth();
    final int imgHeight = (int) pageFormat.getImageableHeight();
    if (imgWidth <= 0) {
        throw new PrinterException("Width of printable area is too small.");
    }
    if((table.getRowCount() * table.getRowHeight()) > imgHeight){
        pageIndex++;
    }
    // to pass the page number when formatting the header and footer text
    Object[] pageNumber = new Object[] { new Integer(pageIndex + 1) };
    // fetch the formatted header text, if any
    String headerText = null;
    if (headerFormat != null) {
        headerText = headerFormat.format(pageNumber);
    }

    // fetch the formatted footer text, if any
    String footerText = null;
    if (footerFormat != null) {
        footerText = footerFormat.format(pageNumber);
    }

    // to store the bounds of the header and footer text
    Rectangle2D hRect = null;
    Rectangle2D fRect = null;

    // the amount of vertical space needed for the header and footer text
    int headerTextSpace = 0;
    int footerTextSpace = 0;

    // the amount of vertical space available for printing the table
    int availableSpace = imgHeight;
    System.out.println("available space: " + availableSpace);
    System.out.println("the avail space // row Height => " + 
    (availableSpace/table.getRowHeight()));
    // if there's header text, find out how much space is needed for it
    // and subtract that from the available space
    if (headerText != null) {
        graphics.setFont(headerFont);
        hRect = graphics.getFontMetrics().getStringBounds(headerText, 
         graphics);

        headerTextSpace = (int) Math.ceil(hRect.getHeight());
        availableSpace -= headerTextSpace + H_F_SPACE;
    }

    // if there's footer text, find out how much space is needed for it
    // and subtract that from the available space
    if (footerText != null) {
        graphics.setFont(footerFont);
        fRect = graphics.getFontMetrics().getStringBounds(footerText, 
         graphics);

        footerTextSpace = (int) Math.ceil(fRect.getHeight());
        availableSpace -= footerTextSpace;// TODO
    }

    if (availableSpace <= 0) {
        throw new PrinterException("Height of printable area is too 
     small.");
    }
    // depending on the print mode, we may need a scale factor to
    // fit the table's entire width on the page
    double sf = 1.0D;
    if (printMode == JTable.PrintMode.FIT_WIDTH && totalColWidth > imgWidth) 
     {

        // if not, we would have thrown an acception previously
        assert imgWidth > 0;

        // it must be, according to the if-condition, since imgWidth > 0
        assert totalColWidth > 1;

        sf = (double) imgWidth / (double) totalColWidth;
    }

    // dictated by the previous two assertions
    assert sf > 0;

    // This is in a loop for two reasons:
    // First, it allows us to catch up in case we're called starting
    // with a non-zero pageIndex. Second, we know that we can be called
    // for the same page multiple times. The condition of this while
    // loop acts as a check, ensuring that we don't attempt to do the
    // calculations again when we are called subsequent times for the
    // same page.
    while (last < pageIndex) {
        // if we are finished all columns in all rows
        if (row >= table.getRowCount() && col == 0) {
            return NO_SUCH_PAGE;
        }
        // rather than multiplying every row and column by the scale factor
        // in findNextClip, just pass a width and height that have already
        // been divided by it
        int scaledWidth = (int) (imgWidth / sf);
        int scaledHeight = (int) ((availableSpace - hclip.height) / sf);
        // calculate the area of the table to be printed for this page
        findNextClip(scaledWidth, scaledHeight);

        last++;
    }

    // translate into the co-ordinate system of the pageFormat
    Graphics2D g2d = (Graphics2D) graphics;
    g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

    // to save and store the transform
    AffineTransform oldTrans;

    // if there's footer text, print it at the bottom of the imageable area
    if (footerText != null) {
        oldTrans = g2d.getTransform();

        g2d.translate(0, imgHeight - footerTextSpace);

        printFooterText(g2d, footerText, fRect, footerFont, imgWidth);

        g2d.setTransform(oldTrans);
    }

    // if there's header text, print it at the top of the imageable area
    // and then translate downwards
    if (headerText != null) {
        printHeaderText(g2d, headerText, hRect, headerFont, imgWidth);

        g2d.translate(0, headerTextSpace + H_F_SPACE);
    }

    // constrain the table output to the available space
    tempRect.x = 0;
    tempRect.y = 0;
    tempRect.width = imgWidth;
    tempRect.height = availableSpace;
    g2d.clip(tempRect);

    // if we have a scale factor, scale the graphics object to fit
    // the entire width
    if (sf != 1.0D) {
        g2d.scale(sf, sf);

        // otherwise, ensure that the current portion of the table is
        // centered horizontally
    } else {
        int diff = (imgWidth - clip.width) / 2;
        g2d.translate(diff, 0);
    }

    // store the old transform and clip for later restoration
    oldTrans = g2d.getTransform();
    Shape oldClip = g2d.getClip();

    // if there's a table header, print the current section and
    // then translate downwards
    if (header != null) {
        hclip.x = clip.x;
        hclip.width = clip.width;

        g2d.translate(-hclip.x, 0);
        g2d.clip(hclip);
        header.print(g2d);

        // restore the original transform and clip
        g2d.setTransform(oldTrans);
        g2d.setClip(oldClip);

        // translate downwards
        g2d.translate(0, hclip.height);
    }

    // print the current section of the table
    g2d.translate(-clip.x, -clip.y);
    g2d.clip(clip);
    table.print(g2d);

    // restore the original transform and clip
    g2d.setTransform(oldTrans);
    g2d.setClip(oldClip);

    // draw a box around the table
    g2d.setColor(Color.BLACK);
    g2d.drawRect(0, 0, clip.width, hclip.height + clip.height);

    return PAGE_EXISTS;
}

/**
 * A helper method that encapsulates common code for rendering the header
 * and footer text.
 * 
 * @param g2d
 *            the graphics to draw into
 * @param text
 *            the text to draw, non null
 * @param rect
 *            the bounding rectangle for this text, as calculated at the
 *            given font, non null
 * @param font
 *            the font to draw the text in, non null
 * @param imgWidth
 *            the width of the area to draw into
 */
private void printHeaderText(Graphics2D g2d, String text, Rectangle2D rect, 
 Font font, int imgWidth) {

    int tx;// TODO

    // if the text is small enough to fit, center it
    if (rect.getWidth() < imgWidth) {
        tx = (int) ((imgWidth - rect.getWidth()) / 2);

        // otherwise, if the table is LTR, ensure the left side of
        // the text shows; the right can be clipped
    } else if (table.getComponentOrientation().isLeftToRight()) {
        tx = 0;

        // otherwise, ensure the right side of the text shows
    } else {
        tx = -(int) (Math.ceil(rect.getWidth()) - imgWidth);
    }

    int ty = (int) Math.ceil(Math.abs(rect.getY()));
    g2d.setColor(Color.BLACK);
    g2d.setFont(MainUi.fLiner);
    g2d.drawString(text, tx, ty);
}

private void printFooterText(Graphics2D g2d, String text, Rectangle2D rect, 
Font font, int imgWidth) {

    int tx;// TODO

    // if the text is small enough to fit, center it
    if (rect.getWidth() < imgWidth) {
        tx = (int) ((imgWidth - rect.getWidth()) / 2);

        // otherwise, if the table is LTR, ensure the left side of
        // the text shows; the right can be clipped
    } else if (table.getComponentOrientation().isLeftToRight()) {
        tx = 0;

        // otherwise, ensure the right side of the text shows
    } else {
        tx = -(int) (Math.ceil(rect.getWidth()) - imgWidth);
    }

   //       int ty = (int) Math.ceil(Math.abs(rect.getY() + 30));
    int ty = (int) Math.ceil(rect.getHeight());
    g2d.setColor(Color.BLACK);
    g2d.setFont(MainUi.ffLiner);
    g2d.drawString(text, tx, ty-3);
}

/**
 * Calculate the area of the table to be printed for the next page. This
 * should only be called if there are rows and columns left to print.
 * 
 * To avoid an infinite loop in printing, this will always put at least one
 * cell on each page.
 * 
 * @param pw
 *            the width of the area to print in
 * @param ph
 *            the height of the area to print in
 */
private void findNextClip(int pw, int ph) {
    final boolean ltr = table.getComponentOrientation().isLeftToRight();

    // if we're ready to start a new set of rows
    if (col == 0) {
        if (ltr) {
            // adjust clip to the left of the first column
            clip.x = 0;
        } else {
            // adjust clip to the right of the first column
            clip.x = totalColWidth;
        }

        // adjust clip to the top of the next set of rows
        clip.y += clip.height;

        // adjust clip width and height to be zero
        clip.width = 0;
        clip.height = 0;

        // fit as many rows as possible, and at least one
        int rowCount = table.getRowCount();
        int rowHeight = table.getRowHeight(row);
        do {
            clip.height += rowHeight;

            if (++row >= rowCount) {
                break;
            }

            rowHeight = table.getRowHeight(row);
        } while (clip.height + rowHeight <= ph);
    }

    // we can short-circuit for JTable.PrintMode.FIT_WIDTH since
    // we'll always fit all columns on the page
    if (printMode == JTable.PrintMode.FIT_WIDTH) {
        clip.x = 0;
        clip.width = totalColWidth;
        return;
    }

    if (ltr) {
        // adjust clip to the left of the next set of columns
        clip.x += clip.width;
    }

    // adjust clip width to be zero
    clip.width = 0;

    // fit as many columns as possible, and at least one
    int colCount = table.getColumnCount();
    int colWidth = colModel.getColumn(col).getWidth();
    do {
        clip.width += colWidth;
        if (!ltr) {
            clip.x -= colWidth;
        }

        if (++col >= colCount) {
            // reset col to 0 to indicate we're finished all columns
            col = 0;

            break;
        }

        colWidth = colModel.getColumn(col).getWidth();
    } while (clip.width + colWidth <= pw);

}

}

  • 1
    Any reason why you're not using the default, built in `Printable` supplied by `JTable`? (which this "seems" to be copy of) – MadProgrammer Jun 20 '17 at 06:23
  • this is not my code and I am debugging it but I can't find the solution to print all pages. – Alireza Aslamzadeh Jun 20 '17 at 10:15
  • [This example](https://stackoverflow.com/questions/26580954/how-to-print-selected-rows-jtable/26581137#26581137), [example](https://stackoverflow.com/questions/24294117/get-jtable-to-print-tabular-format/24297085#24297085), [example](https://stackoverflow.com/questions/34742195/printing-selected-rows-from-jtable/34742430#34742430), [example](https://stackoverflow.com/questions/34086377/printing-a-jpanel-with-scrollable-jtable-on-it/34114959#34114959) – MadProgrammer Jun 20 '17 at 12:43
  • [example](https://stackoverflow.com/questions/33861190/how-to-reduce-width-of-column-and-position-a-jtable-in-java-at-desired-coordinat/33861702#33861702), [example](https://stackoverflow.com/questions/26660448/table-print-does-not-fit-to-page-size/26665276#26665276), [example](https://stackoverflow.com/questions/26598472/printable-not-working-properly/26598867#26598867), [example](https://stackoverflow.com/questions/29788505/cant-generate-complete-data-to-pdf-file-in-java/29792374#29792374) – MadProgrammer Jun 20 '17 at 12:44
  • [example](https://stackoverflow.com/questions/12665089/control-the-size-of-the-panel-on-printed-page/12665357#12665357), [example](https://stackoverflow.com/questions/24977871/printing-selected-component-of-jframe-to-printer/24978159#24978159) or seem to demonstarte printing a `JTable` in one form or another - since I've provided you with countless examples that work, maybe, you'd like to provide us with one that doesn't – MadProgrammer Jun 20 '17 at 12:45
  • thanks, i solved it. – Alireza Aslamzadeh Jul 03 '17 at 06:58

0 Answers0