Print JTable with Multiple pages and rows

I took the printing example at http://java.sun.com/developer/onlineTraining/Programming/JDCBook/advprint.html#pe and modified it a bit to include the following:

1) To Print Multiple pages

2) To wrap lines that is too long for the column

3) To print with a more proffesional style, so that it doesn't look like a screen capture is printed

4) To align the numbers to the right and center column headings

import javax.swing.*;

import javax.swing.table.*;

import java.awt.print.*;

import java.util.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.awt.Dimension;

import javax.print.*;

import javax.print.attribute.*;

import javax.print.attribute.standard.*;

import java.text.*;

publicclass Reportimplements Printable

{

privatefinalint LEFT_ALIGN = -1;

privatefinalint CENTER_ALIGN = 0;

privatefinalint RIGHT_ALIGN = 1;

private JFrame frame;

private JTable tableView;

private String lastPrintDate;

private Font defaultFont;

private Font headerFont;

private Font footerFont;

privateint headerHeight;

privateint footerHeight;

privateint cellBuffer = 5;

privateboolean first_pass;

private ArrayList pages;

public Report()

{

frame =new JFrame("Sales Report");

frame.addWindowListener(new WindowAdapter()

{

publicvoid windowClosing(WindowEvent e)

{

System.exit(0);

}

});

final String[] headers =

{

"ID",

"Description",

"open price",

"latest price",

"End Date",

"Quantity"

};

int count = 0;

final Object[][] data =

{

{new Integer(count++),"Box of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of BirosBox of Biros ppppppppppppppp","1.00","4.99",new Date(),new Integer(200000)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)},

{new Integer(count++),"Blue Biro","0.10","0.14",new Date(),new Integer(1)},

{new Integer(count++),"legal pad","1.00","2.49",new Date(),new Integer(1)},

{new Integer(count++),"tape","1.00","1.49",new Date(),new Integer(1)},

{new Integer(count++),"stapler","4.00","4.49",new Date(),new Integer(1)},

{new Integer(count++),"Box of Biros","1.00","4.99",new Date(),new Integer(2)}

};

TableModel dataModel =new AbstractTableModel()

{

publicint getColumnCount(){return headers.length;}

publicint getRowCount(){return data.length;}

public Object getValueAt(int row,int col)

{

return data[row][col];

}

public String getColumnName(int column)

{

return headers[column];

}

public Class getColumnClass(int col)

{

return getValueAt(0,col).getClass();

}

publicboolean isCellEditable(int row,int col)

{

return (col==1);

}

publicvoid setValueAt(Object aValue,int row,int column)

{

data[row][column] = aValue;

}

};

tableView =new JTable(dataModel);

JScrollPane scrollpane =new JScrollPane(tableView);

scrollpane.setPreferredSize(new Dimension(500, 80));

frame.getContentPane().setLayout(new BorderLayout());

frame.getContentPane().add(BorderLayout.CENTER,scrollpane);

frame.pack();

JButton printButton=new JButton();

printButton.setText("print me!");

frame.getContentPane().add(BorderLayout.SOUTH,printButton);

// for faster printing turn double buffering off

RepaintManager.currentManager(frame).setDoubleBufferingEnabled(false);

printButton.addActionListener(new ActionListener()

{

publicvoid actionPerformed(ActionEvent evt)

{

doPrint();

}

});

frame.setVisible(true);

}

/**

* Reset variables before printing

*/

privatevoid prepareForPrint()

{

pages =new ArrayList();

first_pass =true;

}

/**

* Display a print dialog with some hardcoded defaults

* The print fonts are also hardcoded

*/

publicvoid doPrint()

{

try

{

String jobName ="Java Report";

defaultFont =new Font("Arial", Font.PLAIN, 8);

footerFont =new Font("Arial", Font.PLAIN, 6);

headerFont =new Font("Arial", Font.BOLD, 10);

PrinterJob prnJob = PrinterJob.getPrinterJob();

prnJob.setPrintable(this);

PrintRequestAttributeSet prnSet =new HashPrintRequestAttributeSet();

prnSet.add(new Copies(1));

prnSet.add(new JobName(jobName,null));

prnSet.add(MediaSizeName.ISO_A4);

PageFormat pf = prnJob.defaultPage();

pf.setOrientation(java.awt.print.PageFormat.PORTRAIT);

prnJob.setJobName(jobName);

PrintService[] services = PrinterJob.lookupPrintServices();

if (services.length > 0)

{

if (prnJob.printDialog(prnSet))

{

/*

* Get print date

*/

String dateFormat ="dd/MM/yyyy HH:mm:ss";

DateFormat m_DateFormat =new SimpleDateFormat(dateFormat);

lastPrintDate = m_DateFormat.format(new Date()).toString();

prepareForPrint();

prnJob.print(prnSet);

}

}

else

{

JOptionPane.showMessageDialog(frame,"No Printer was found!!","Printer Error", JOptionPane.ERROR_MESSAGE);

return;

}

}

catch (PrinterException e)

{

e.printStackTrace();

}

}

publicint print(Graphics g, PageFormat pageFormat,int pageIndex)throws PrinterException

{

/**

* Check if this is the first time the print method is called for this print action.

* It is not guaranteed that the print will be called with synchronous pageIndex'es,

* so we need to calculate the number of pages and which rows appear on which pages.

* Then the correct page will be printed regardless of which pageIndex is sent through.

*/

if (first_pass)

{

calcPages(g, pageFormat);

}

first_pass =false;

// Stop printing if the pageIndex is out of range

if (pageIndex >= pages.size())

{

return NO_SUCH_PAGE;

}

Graphics2Dg2 = (Graphics2D) g;

g2.setColor(Color.black);

// The footer will be one line at the bottom of the page, cater for this.

g2.setFont(footerFont);

footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();

g2.setFont(defaultFont);

FontMetrics fontMetrics = g2.getFontMetrics();

int fontHeight = fontMetrics.getHeight();

int fontDescent = fontMetrics.getDescent();

double pageHeight = pageFormat.getImageableHeight() + pageFormat.getImageableY();

double pageWidth = pageFormat.getImageableWidth();

double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();

// Shrink or expand the table to fit the page width

double scale = pageWidth / (tableWidth+ (cellBuffer * tableView.getColumnCount()));

// Calculate the width in pixels for each column

double[] columnWidths =newdouble[tableView.getColumnCount()];

for(int i = 0; i < tableView.getColumnCount(); i++)

{

columnWidths[i] = (double)tableView.getColumnModel().getColumn(i).getWidth() * scale;

}

// Reset the view to the start of the page

g2.translate(0, 0);

/*

// Draw a rectangle to see the printable area

g2.draw3DRect((int)pageFormat.getImageableX(),

(int)pageFormat.getImageableY(),

(int)pageFormat.getImageableWidth(),

(int)pageFormat.getImageableHeight(),

false);

*/

// Calculate the header height

g2.setFont(headerFont);

fontMetrics = g2.getFontMetrics();

// Print the headers and retreive the starting position for the data

int next_row = printLine(g2, pageFormat, fontMetrics, -1, (int)pageFormat.getImageableY() + fontHeight, columnWidths);

g2.setFont(defaultFont);

fontMetrics = g2.getFontMetrics();

// Start printing the detail

ArrayList page = (ArrayList)pages.get(pageIndex);

int start = ((Integer)page.get(0)).intValue();

int end = ((Integer)page.get(1)).intValue();

for (int i = start; i <= end; i++)

{

next_row = printLine(g2, pageFormat, fontMetrics, i, next_row, columnWidths);

}

// Print the footer

g2.setFont(footerFont);

String pageFooter ="Page " + (pageIndex + 1) +" - " + lastPrintDate;

g2.drawString(pageFooter,

(int)pageFormat.getWidth() / 2 - (fontMetrics.stringWidth(pageFooter) / 2),

(int)(pageHeight - fontDescent));

return PAGE_EXISTS;

}

/**

* We can't guarantee that the same amount of rows will be displayed on each page,

* the row heights are dynamic and may wrap onto 2 or more lines.

* Thus we need to calculate the height of each row and then test how may rows

* fit on a specific page. eg. Page 1 contains rows 1 to 10, Page 2 contains rows 11 to 15 etc.

*/

publicvoid calcPages(Graphics g, PageFormat pageFormat)throws PrinterException

{

Graphics2Dg2 = (Graphics2D) g;

g2.setColor(Color.black);

// The footer will be one line at the bottom of the page, cater for this.

g2.setFont(footerFont);

footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();

g2.setFont(defaultFont);

FontMetrics fontMetrics = g2.getFontMetrics();

int fontHeight = fontMetrics.getHeight();

int fontDescent = fontMetrics.getDescent();

double pageHeight = pageFormat.getImageableHeight() - fontHeight;

double pageWidth = pageFormat.getImageableWidth();

double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();

// Shrink or expand the table to fit the page width

double scale = pageWidth / (tableWidth+ (cellBuffer * tableView.getColumnCount()));

// Calculate the width in pixels for each column

double[] columnWidths =newdouble[tableView.getColumnCount()];

for(int i = 0; i < tableView.getColumnCount(); i++)

{

columnWidths[i] = (double)tableView.getColumnModel().getColumn(i).getWidth() * scale;

}

// Calculate the header height

int maxHeight = 0;

g2.setFont(headerFont);

fontMetrics = g2.getFontMetrics();

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value = tableView.getColumnName(j).toString();

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

}

headerHeight = g2.getFontMetrics().getHeight() * maxHeight;

g2.setFont(defaultFont);

fontMetrics = g2.getFontMetrics();

int pageNum = 0;

int bottom_of_page = (int)(pageFormat.getImageableHeight() + pageFormat.getImageableY()) - footerHeight;

int prev_row = 0;

int next_row = (int)pageFormat.getImageableY() + fontHeight + headerHeight;

int i = 0;

ArrayList page =new ArrayList();

page.add(new Integer(0));

for (i = 0; i < tableView.getRowCount(); i++)

{

maxHeight = 0;

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value = tableView.getValueAt(i, j).toString();

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

}

prev_row = next_row;

next_row += (fontHeight * maxHeight);

// If we've reached the bottom of the page then set the current page's end row

if (next_row > bottom_of_page)

{

page.add(new Integer(i - 1));

pages.add(page);

page =new ArrayList();

page.add(new Integer(i));

pageNum++;

next_row = (int)pageFormat.getImageableY()

+ fontHeight

+ ((int)pageFormat.getHeight() * pageNum)

+ headerHeight;

bottom_of_page = (int)(pageFormat.getImageableHeight()

+ pageFormat.getImageableY())

+ ((int)pageFormat.getHeight() * pageNum)

- footerHeight;

//Include the current row on the next page, because there is no space on this page

i--;

}

}

page.add(new Integer(i - 1));

pages.add(page);

}

/**

* Print the headers or a row from the table to the graphics context

* Return the position of the row following this one

*/

publicint printLine(Graphics2D g2,

PageFormat pageFormat,

FontMetrics fontMetrics,

int rowNum,

int next_row,

double[] columnWidths)

throws PrinterException

{

int lead = 0;

int maxHeight = 0;

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value =null;

int align = LEFT_ALIGN;

if (rowNum > -1)

{

Object obj = tableView.getValueAt(rowNum, j);

if (objinstanceof Number)

{

align = RIGHT_ALIGN;

}

value = obj.toString();

}

else

{

align = CENTER_ALIGN;

value = tableView.getColumnName(j);

}

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

if (fontMetrics.stringWidth(value) < columnWidths[j])

{

// Single line

int offset = 0;

// Work out the offset from the start of the column to display alignment correctly

switch (align)

{

case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value));break;

case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2;break;

default: offset = 0;break;

}

g2.drawString(value,

lead + (int)(pageFormat.getImageableX() + offset),

next_row);

}

else

{

for(int a = 0; a < numLines; a++)

{

//Multi-Line

int x = 0;

int width = 0;

for(x = 0; x < value.length(); x++)

{

width += fontMetrics.charWidth(value.charAt(x));

if (width > columnWidths[j])

{

break;

}

}

int offset = 0;

// Work out the offset from the start of the column to display alignment correctly

switch (align)

{

case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value));break;

case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2;break;

default: offset = 0;break;

}

g2.drawString(value.substring(0, x),

lead + (int)(pageFormat.getImageableX() + offset),

next_row + (fontMetrics.getHeight() * a));

value = value.substring(x);

}

}

lead += columnWidths[j] + cellBuffer;

}

// Draw a solid line below the row

g2.draw(new Line2D.Double(pageFormat.getImageableX(),

next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent(),

pageFormat.getImageableY() + pageFormat.getImageableWidth(),

next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent()));

// Return the position of the row following this one

return next_row + (fontMetrics.getHeight() * maxHeight);

}

publicstaticvoid main(String[] args)

{

new Report();

}

}

[36596 byte] By [JohannHough] at [2007-9-30 23:18:57]
# 1

Fixed some bugs and added a title. Just pass in a JTable and the class will do the rest.

import javax.swing.*;

import javax.swing.table.*;

import java.awt.print.*;

import java.util.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import javax.print.*;

import javax.print.attribute.*;

import javax.print.attribute.standard.*;

import java.text.*;

import java.math.*;

public class PrintJTable implements Printable

{

private final int LEFT_ALIGN = -1;

private final int CENTER_ALIGN = 0;

private final int RIGHT_ALIGN = 1;

private JFrame m_parent;

private String m_title;

private JTable tableView;

private String lastPrintDate;

private Font defaultFont;

private Font headerFont;

private Font footerFont;

private int headerHeight;

private int footerHeight;

private int cellBuffer = 5;

private boolean first_pass;

private ArrayList pages;

public PrintJTable(JFrame parent, JTable table)

{

m_parent = parent;

tableView = table;

doPrint();

}

public PrintJTable(JFrame parent, String title, JTable table)

{

m_parent = parent;

m_title = title;

tableView = table;

doPrint();

}

/**

* Reset variables before printing

*/

private void prepareForPrint()

{

pages = new ArrayList();

first_pass = true;

}

/**

* Display a print dialog with some hardcoded defaults

* The print fonts are also hardcoded

*/

public void doPrint()

{

try

{

String jobName = "Java Report";

defaultFont = new Font("Arial", Font.PLAIN, 8);

footerFont = new Font("Arial", Font.PLAIN, 6);

headerFont = new Font("Arial", Font.BOLD, 8);

PrinterJob prnJob = PrinterJob.getPrinterJob();

prnJob.setPrintable(this);

PrintRequestAttributeSet prnSet = new HashPrintRequestAttributeSet();

prnSet.add(new Copies(1));

prnSet.add(new JobName(jobName, null));

prnSet.add(MediaSizeName.ISO_A4);

PageFormat pf = prnJob.defaultPage();

pf.setOrientation(java.awt.print.PageFormat.PORTRAIT);

prnJob.setJobName(jobName);

PrintService[] services = PrinterJob.lookupPrintServices();

if (services.length > 0)

{

if (prnJob.printDialog(prnSet))

{

/*

* Get print date

*/

String dateFormat = "dd/MM/yyyy HH:mm:ss";

DateFormat m_DateFormat = new SimpleDateFormat(dateFormat);

lastPrintDate = m_DateFormat.format(new Date()).toString();

prepareForPrint();

prnJob.print(prnSet);

}

}

else

{

JOptionPane.showMessageDialog(m_parent, "No Printer was found!!", "Printer Error", JOptionPane.ERROR_MESSAGE);

return;

}

}

catch (PrinterException e)

{

e.printStackTrace();

}

}

public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException

{

/**

* Check if this is the first time the print method is called for this print action.

* It is not guaranteed that the print will be called with synchronous pageIndex'es,

* so we need to calculate the number of pages and which rows appear on which pages.

* Then the correct page will be printed regardless of which pageIndex is sent through.

*/

if (first_pass)

{

calcPages(g, pageFormat);

}

first_pass = false;

// Stop printing if the pageIndex is out of range

if (pageIndex >= pages.size())

{

return NO_SUCH_PAGE;

}

Graphics2Dg2 = (Graphics2D) g;

g2.setColor(Color.black);

// The footer will be one line at the bottom of the page, cater for this.

g2.setFont(footerFont);

footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();

g2.setFont(defaultFont);

FontMetrics fontMetrics = g2.getFontMetrics();

int fontHeight = fontMetrics.getHeight();

int fontDescent = fontMetrics.getDescent();

double pageHeight = pageFormat.getImageableHeight() + pageFormat.getImageableY();

double pageWidth = pageFormat.getImageableWidth();

double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();

// Shrink or expand the table to fit the page width

double scale = (pageWidth - (cellBuffer * tableView.getColumnCount())) / tableWidth;

// Calculate the width in pixels for each column

double[] columnWidths = new double[tableView.getColumnCount()];

double test = 0;

for(int i = 0; i < tableView.getColumnCount(); i++)

{

columnWidths[i] = (double)Math.floor(tableView.getColumnModel().getColumn(i).getWidth() * scale);

test += columnWidths[i];

}

// Reset the view to the start of the page

g2.translate(0, 0);

/*

// Draw a rectangle to see the printable area

g2.draw3DRect((int)pageFormat.getImageableX(),

(int)pageFormat.getImageableY(),

(int)pageFormat.getImageableWidth(),

(int)pageFormat.getImageableHeight(),

false);

*/

// Calculate the header height

g2.setFont(headerFont);

fontMetrics = g2.getFontMetrics();

// Print the headers and retreive the starting position for the data

int next_row = (int)pageFormat.getImageableY() + fontMetrics.getHeight();

if ((m_title != null) && (!m_title.equalsIgnoreCase("")))

{

g2.drawString(m_title,

(int)(pageFormat.getImageableX()),

next_row);

Color current_color = g2.getColor();

g2.setColor(Color.lightGray);

int y = next_row + fontMetrics.getDescent();

g2.draw(new Line2D.Double(pageFormat.getImageableX(),

y,

(pageFormat.getImageableY() + pageFormat.getImageableWidth()),

y));

g2.setColor(current_color);

next_row += fontMetrics.getHeight();

}

next_row = printLine(g2, pageFormat, fontMetrics, -1, next_row, columnWidths);

g2.setFont(defaultFont);

fontMetrics = g2.getFontMetrics();

// Start printing the detail

ArrayList page = (ArrayList)pages.get(pageIndex);

int start = ((Integer)page.get(0)).intValue();

int end = ((Integer)page.get(1)).intValue();

for (int i = start; i <= end; i++)

{

next_row = printLine(g2, pageFormat, fontMetrics, i, next_row, columnWidths);

}

// Print the footer

g2.setFont(footerFont);

String pageFooter = "Page " + (pageIndex + 1) + " - " + lastPrintDate;

g2.drawString(pageFooter,

(int)pageFormat.getWidth() / 2 - (fontMetrics.stringWidth(pageFooter) / 2),

(int)(pageHeight - fontDescent));

return PAGE_EXISTS;

}

/**

* We can't guarantee that the same amount of rows will be displayed on each page,

* the row heights are dynamic and may wrap onto 2 or more lines.

* Thus we need to calculate the height of each row and then test how may rows

* fit on a specific page. eg. Page 1 contains rows 1 to 10, Page 2 contains rows 11 to 15 etc.

*/

public void calcPages(Graphics g, PageFormat pageFormat) throws PrinterException

{

Graphics2Dg2 = (Graphics2D) g;

g2.setColor(Color.black);

// The footer will be one line at the bottom of the page, cater for this.

g2.setFont(footerFont);

footerHeight = g2.getFontMetrics().getHeight() + g2.getFontMetrics().getDescent();

g2.setFont(defaultFont);

FontMetrics fontMetrics = g2.getFontMetrics();

int fontHeight = fontMetrics.getHeight();

int fontDescent = fontMetrics.getDescent();

double pageHeight = pageFormat.getImageableHeight() - fontHeight;

double pageWidth = pageFormat.getImageableWidth();

double tableWidth = (double) tableView.getColumnModel().getTotalColumnWidth();

// Shrink or expand the table to fit the page width

double scale = (pageWidth - (cellBuffer * tableView.getColumnCount())) / tableWidth;

// Calculate the width in pixels for each column

double[] columnWidths = new double[tableView.getColumnCount()];

for(int i = 0; i < tableView.getColumnCount(); i++)

{

columnWidths[i] = (double)Math.floor(tableView.getColumnModel().getColumn(i).getWidth() * scale);

}

// Calculate the header height

int maxHeight = 0;

g2.setFont(headerFont);

fontMetrics = g2.getFontMetrics();

headerHeight = 0;

if ((m_title != null) && (!m_title.equalsIgnoreCase("")))

{

headerHeight = fontMetrics.getHeight();

}

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value = tableView.getColumnName(j).toString();

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

}

headerHeight += g2.getFontMetrics().getHeight() * maxHeight;

g2.setFont(defaultFont);

fontMetrics = g2.getFontMetrics();

int pageNum = 0;

int bottom_of_page = (int)(pageFormat.getImageableHeight() + pageFormat.getImageableY()) - footerHeight;

int prev_row = 0;

int next_row = (int)pageFormat.getImageableY() + fontHeight + headerHeight;

int i = 0;

ArrayList page = new ArrayList();

page.add(new Integer(0));

for (i = 0; i < tableView.getRowCount(); i++)

{

maxHeight = 0;

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value = formatObject(tableView.getValueAt(i, j));

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

}

prev_row = next_row;

next_row += (fontHeight * maxHeight);

// If we've reached the bottom of the page then set the current page's end row

if (next_row > bottom_of_page)

{

page.add(new Integer(i - 1));

pages.add(page);

page = new ArrayList();

page.add(new Integer(i));

pageNum++;

next_row = (int)pageFormat.getImageableY()

+ fontHeight

+ ((int)pageFormat.getHeight() * pageNum)

+ headerHeight;

bottom_of_page = (int)(pageFormat.getImageableHeight()

+ pageFormat.getImageableY())

+ ((int)pageFormat.getHeight() * pageNum)

- footerHeight;

//Include the current row on the next page, because there is no space on this page

i--;

}

}

page.add(new Integer(i - 1));

pages.add(page);

}

/**

* Print the headers or a row from the table to the graphics context

* Return the position of the row following this one

*/

public int printLine(Graphics2D g2,

PageFormat pageFormat,

FontMetrics fontMetrics,

int rowNum,

int next_row,

double[] columnWidths)

throws PrinterException

{

int lead = 0;

int maxHeight = 0;

for (int j = 0; j < tableView.getColumnCount(); j++)

{

String value = null;

int align = LEFT_ALIGN;

if (rowNum > -1)

{

Object obj = tableView.getValueAt(rowNum, j);

if (obj instanceof Number)

{

align = RIGHT_ALIGN;

}

value = formatObject(obj);

}

else

{

//align = CENTER_ALIGN;

value = tableView.getColumnName(j);

}

int numLines = (int)Math.ceil(fontMetrics.stringWidth(value) / columnWidths[j]);

if (numLines > maxHeight)

{

maxHeight = numLines;

}

if (fontMetrics.stringWidth(value) < columnWidths[j])

{

// Single line

int offset = 0;

// Work out the offset from the start of the column to display alignment correctly

switch (align)

{

case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)); break;

case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value)) / 2; break;

default: offset = 0; break;

}

g2.drawString(value,

lead + (int)(pageFormat.getImageableX() + offset),

next_row);

}

else

{

for(int a = 0; a < numLines; a++)

{

//Multi-Line

int x = 0;

int width = 0;

for(x = 0; x < value.length(); x++)

{

width += fontMetrics.charWidth(value.charAt(x));

if (width > columnWidths[j])

{

break;

}

}

int offset = 0;

// Work out the offset from the start of the column to display alignment correctly

switch (align)

{

case RIGHT_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value.substring(0, x))); break;

case CENTER_ALIGN: offset = (int)(columnWidths[j] - fontMetrics.stringWidth(value.substring(0, x))) / 2; break;

default: offset = 0; break;

}

g2.drawString(value.substring(0, x),

lead + (int)(pageFormat.getImageableX() + offset),

next_row + (fontMetrics.getHeight() * a));

value = value.substring(x);

}

}

lead += columnWidths[j] + cellBuffer;

}

// Draw a solid line below the row

Color current_color = g2.getColor();

g2.setColor(Color.lightGray);

int y = next_row + (fontMetrics.getHeight() * (maxHeight - 1)) + fontMetrics.getDescent();

g2.draw(new Line2D.Double(pageFormat.getImageableX(),

y,

(pageFormat.getImageableY() + pageFormat.getImageableWidth()),

y));

g2.setColor(current_color);

// Return the position of the row following this one

return next_row + (fontMetrics.getHeight() * maxHeight);

}

public String formatObject(Object obj)

{

String value = (obj == null) ? "" : obj.toString();

return value;

}

}

JohannHough at 2007-7-7 13:51:55 > top of Java-index,Java Essentials,Java Programming...