Printing JTable with DefaultTableCellRenderer (or JLabel's)

Hi there,
I am trying to print a JTable by having it implement the Printable interface. It works, but it works only because I use the string values from the renderers of the cells. This works fine if its just simple left alligned strings.
But when you are using formatted text strings for instance (in a DefaultTableCellRenderer extension) or something that represents a boolean (a checkbox), it doesn't look very good. Bad actually. I tried to use the print method on the renderer or cast them first to a JComponent or JLabel and then use the print method. No success so far. Can anybody help me? I am quit desperate right now.
Kind regards,
Ren�

Yes I can. I took the print method from the class in which I implemented it (the JTable is a member of that particular class):
* Implementing the Printable interface.
* For printing the same font is used as is used on the screen.
* So, no special print font is used or can be choosen at this
* point. Also the font size is taken from the table on screen.
* The title font is twice the font size of the normal font, but
* bold. The column headers have the same font as the normal font
* but also bold like the title.
* The height we'll be using for a line of text will be 1.5 times
* the average height in this font, with a minimum of 10.
* The title font, the table header font and the table content font
* are all the same (unlike the table) and based on the table font.
* The table header font is not used.
* If the table does not fit on paper, one could adjust the orientation
* of the paper in the paper dialog, or adjust the distance bewtween
* the columns on the screen as the column width on the screen is
* taken to the paper.
public int print(Graphics pg, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex >= m_maxNumPage) {
return NO_SUCH_PAGE;
// This is for anti aliasing.
Graphics2D g2d = null;
if (pg instanceof Graphics2D) {
g2d = (Graphics2D) pg;
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
pg.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());
int wPage = (int) pageFormat.getImageableWidth();
int hPage = (int) pageFormat.getImageableHeight();
// This will make sure no printing is
// done outside the designated area.
pg.setClip(0, 0, wPage, hPage);
// Forget this: its a test (works fine though).
//table.print(g2d);
//if (true)
// return PAGE_EXISTS;
int y = 0;
// Make the title font size twice the size of the regular font size.
pg.setFont(this.table.getFont().deriveFont(Font.BOLD, (this.table.getFont().getSize() * 2)));
pg.setColor(Color.black);
FontMetrics fm = pg.getFontMetrics();
y += fm.getAscent();
// Draw the title, the date and the page number.
pg.drawString(pageTitle + " " + DateFormat.getDateInstance(DateFormat.MEDIUM, this.locale).format(new Date(System.currentTimeMillis())) + " (" + (pageIndex + 1) + ") ", 0, y);
//          pg.drawString(pageTitle + " " + DateFormat.getDateInstance().format(new Date(System.currentTimeMillis())) + " (" + (pageIndex + 1) + ") ", 0, y);
y += 20; // space between title and table headers
// The font for the table headers.
Font headerFont = this.table.getTableHeader().getFont();
pg.setFont(headerFont);
fm = pg.getFontMetrics();
TableColumnModel colModel = this.table.getColumnModel();
int nColumns = colModel.getColumnCount();
int x[] = new int[nColumns];
x[0] = 0;
int h = fm.getAscent();
// Add ascent of header font because of baseline positioning.
y += h;
int nRow, nCol;
// Draw the COLUMN HEADERS.
for (nCol = 0; nCol < nColumns; nCol++) {
TableColumn tk = colModel.getColumn(nCol);
int width = tk.getWidth();
String title = (String) tk.getIdentifier();
// The x offset for each column stored.
if (nCol + 1 < nColumns) {
x[nCol + 1] = x[nCol] + width;
// If this is not the last column header, calculated
// how many characters can be printed, based on the
// width of the column being printed.
if ((nCol < (nColumns - 1)) && title.length() > 0) {
//if (x[nCol] + width <= wPage) {
for (int i = title.length(); i >= 0; i--) {
if ((fm.stringWidth(title.substring(0, i))) <= width) {
// Adjust the colum header for the space available (the width).
title = title.substring(0, i);
break;
// Draw the column header.
pg.drawString(title, x[nCol], y);
pg.setFont(this.table.getFont());
fm = pg.getFontMetrics();
int header = y;
// Gets the standard height of a line of text in this font.
// This is the distance between the baseline of adjacent lines of text.
// It is the sum of the leading + ascent + descent. There is no guarantee
// that lines of text spaced at this distance are disjoint; such lines may
// overlap if some characters overshoot either the standard ascent or the
// standard descent metric.
h = fm.getHeight();
// Calculate the ACTUAL height we'll be using for a line of text.
// That would be 1.5 times the average height, with a minimum of 10.
// Actually, normally, the average height should suffice. But we're
// not taking any risks here.
int rowHeight = Math.max((int) (h * 1.5), 10);
// Calculate how many rows fit on a page.
int rowPerPage = (hPage - header) / rowHeight;
m_maxNumPage = Math.max((int) Math.ceil(this.table.getRowCount() / (double) rowPerPage), 1);
int iniRow = pageIndex * rowPerPage;
int endRow = Math.min(this.table.getRowCount(), iniRow + rowPerPage);
String cell = null;
// Draw every ROW.
for (nRow = iniRow; nRow < endRow; nRow++) {
y += rowHeight;
// Draw each CELL in each ROW.
for (nCol = 0; nCol < nColumns; nCol++) {
cell = null;
int col = this.table.getColumnModel().getColumn(nCol).getModelIndex();
// Get the cell object. This is the object that needs to be printed.
Object object = model.getValueAt(nRow, col);
// RENDERING FOR PRINTING! Here is determined for the printing how the rendering is done.
// If a special renderer had been set an attempt is made to use that renderer (e.g. get the text).
// If that is not possible, simple rendering: the toString() value.
// BE AWARE! The format for numbers, booleans etc. might require better code.
if (table.getColumnModel().getColumn(nCol).getCellRenderer() != null) {
if (table.getColumnModel().getColumn(nCol).getCellRenderer().getTableCellRendererComponent(table, object, false, false, nRow, nCol) != null) {
if (table.getColumnModel().getColumn(nCol).getCellRenderer().getTableCellRendererComponent(table, object, false, false, nRow, nCol) instanceof JLabel) {
cell = ((JLabel) table.getColumnModel().getColumn(nCol).getCellRenderer().getTableCellRendererComponent(table, object, false, false, nRow, nCol)).getText();
//table.getCellRenderer(0, nCol).getTableCellRendererComponent(table, object, false, false, 0, nCol).paint(g2d);
// Object fiets = table.getCellRenderer(0, nCol).getTableCellRendererComponent(table, object, false, false, 0, nCol);
// if (fiets instanceof DefaultTableCellRenderer) {
//      System.out.println("DefaultTableCellRenderer!" + nCol);
//      ((DefaultTableCellRenderer) fiets).print(pg);
// If the object is a Boolean, print an "X" or an "O".
if (object instanceof Boolean) {
cell = (((Boolean) object).equals(new Boolean(true)) ? "X" : "O");
// Still don't know how to print it? Use the object's toString() method.
// This is probably used in most cases anyway!
if (cell == null && object != null) {
//cell = object.toString();
if (cell == null) {
cell = "";
// If this is not the last column, calculated how many
// characters can be printed, based on the width of
// the column being printed.
if ((nCol < (nColumns - 1)) && cell.length() > 0) {
int width = colModel.getColumn(nCol).getWidth();
for (int i = cell.length(); i >= 0; i--) {
if ((fm.stringWidth(cell.substring(0, i))) <= width) {
// Adjust the size.
cell = cell.substring(0, i);
break;
// Print the cell.
pg.drawString(cell, x[nCol], y);
System.gc();
return PAGE_EXISTS;
}

Similar Messages

  • Print Jtable with multiline header?

    i want to print jtable with multi-lines header and footer
    using the print function that takes MessageFormat as header and footer
    i used MessageFormat header = new MessageFormat("hello\r\nworld");and i used '\n' only
    but it was printed all in the same line
    thnx in advance

    You can try something on the below lines. Set your custom renderer for the tableheader.
    public class MultiLineHeaderRenderer extends DefaultTableCellRenderer{
            public Component getTableCellRendererComponent(JTable table, Object value,
                             boolean isSelected, boolean hasFocus, int row, int column) {
                         JLabel label = (JLabel) super.getTableCellRendererComponent( table,  value,
                              isSelected,  hasFocus,  row,  column);
                        label.setText("<html>a<br>b</html>");
                        return label;
        }Not the best way to do it. And might need to some modifications too to set the font position etc.

  • 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.*;
    public class Report implements Printable
         private final int LEFT_ALIGN = -1;
         private final int CENTER_ALIGN = 0;
         private final int RIGHT_ALIGN = 1;
         private JFrame frame;
         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 Report()
              frame = new JFrame("Sales Report");
              frame.addWindowListener(new WindowAdapter()
                   public void 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()
                   public int getColumnCount() { return headers.length; }
                   public int 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();
                   public boolean isCellEditable(int row, int col)
                        return (col==1);
                   public void 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()
                   public void actionPerformed(ActionEvent evt)
                        doPrint();
              frame.setVisible(true);
          * 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, 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();
         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;
              Graphics2D     g2 = (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 = new double[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.
         public void calcPages(Graphics g, PageFormat pageFormat) throws PrinterException
              Graphics2D     g2 = (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 = new double[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
         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 = 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);
         public static void main(String[] args)
              new Report();
    }

    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;
              Graphics2D     g2 = (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;
              // 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
              Graphics2D     g2 = (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;

  • Print - JTable with a TITLE on each page

    Hi! someone know haw can I print a MY TITLE on each page that I print ?
    ----->MY TITLE<----
    | co1 | col2 | col3 | col4 |
    |dtxxz|dtxyz|dtxyz|dtxyz|
    |dtxxz|dtxyz|dtxyz|dtxyz|
    |dtxxz|dtxyz|dtxyz|dtxyz|
    PAGE 1
    I try that :
    g.drawString("MY TITLE", 100,50);
    but the table header hide (writing over) my title
    Here is my call :
    public int print(Graphics g, PageFormat pageFormat, int pageIndex)
    throws PrinterException {
         Graphics2D g2 = (Graphics2D) g;
         g2.setColor(Color.black);
         int fontHeight = g2.getFontMetrics().getHeight();
         int fontDesent = g2.getFontMetrics().getDescent();
         pageFormat.setOrientation(pageFormat.LANDSCAPE);
         //leave room for page number
         double pageHeight = pageFormat.getImageableHeight() - fontHeight;
         double pageWidth = pageFormat.getImageableWidth();
         double tableWidth =
              (double) getCurrentTable().getColumnModel().getTotalColumnWidth();
         double scale = 1;
         if (tableWidth >= pageWidth) {
              scale = pageWidth / tableWidth;
         double headerHeightOnPage =
              getCurrentTable().getTableHeader().getHeight() * scale ;
         double tableWidthOnPage = tableWidth * scale;
         double oneRowHeight =
              (getCurrentTable().getRowHeight() + getCurrentTable().getRowMargin()) * scale;
         int numRowsOnAPage = (int) ((pageHeight - headerHeightOnPage) / oneRowHeight);
         double pageHeightForTable = oneRowHeight * numRowsOnAPage;
         int totalNumPages =
              (int) Math.ceil(((double) getCurrentTable().getRowCount()) / numRowsOnAPage);
         if (pageIndex >= totalNumPages) {
              return NO_SUCH_PAGE;
         g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
         g2.drawString(
              "Page: " + (pageIndex + 1),
              (int) pageWidth / 2 - 35,
              (int) (pageHeight + fontHeight - fontDesent));
         //bottom center
         g2.translate(0f, headerHeightOnPage);
         g2.translate(0f, -pageIndex * pageHeightForTable);
         //TODO this next line treats the last page as a full page
         g2.setClip(
              0,
              (int) (pageHeightForTable * pageIndex),
              (int) Math.ceil(tableWidthOnPage),
              (int) Math.ceil(pageHeightForTable));
         g2.scale(scale, scale);
         getCurrentTable().paint(g2);
         g2.scale(1 / scale, 1 / scale);
         g2.translate(0f, pageIndex * pageHeightForTable);
         g2.translate(0f, -headerHeightOnPage);
         g2.setClip(
              0,
              0,
              (int) Math.ceil(tableWidthOnPage),
              (int) Math.ceil(headerHeightOnPage));
         g2.scale(scale, scale);
         getCurrentTable().getTableHeader().paint(g2); //paint header at top
         return Printable.PAGE_EXISTS;
    Thanks

    //Solution-------------------------------------------------------------------------------------------------------
    // PRINT : CENTER HEADER TITLE ON EACH PAGE
    : PAGE NUMBER ON EACH PAGE
    : USE A PREVIEW WINDOW
    import javax.swing.*;
    import javax.swing.table.*;
    import java.awt.print.*;
    import java.awt.*;
    import java.awt.event.*;
    * File: PrintTable.java
    * (C) Copyright Corp. 2001 - All Rights Reserved.
    * Print a JTable data
    public class PrintTable implements Printable {
    * Insert the method's description here.
    * Creation date: (03-13-2002 13:50:41)
    * @param g java.awt.Graphics
    * @param pg java.awt.print.PageFormat
    * @param i int
    public int print(Graphics g, PageFormat pageFormat,
         int pageIndex) throws PrinterException {
         try{
              Graphics2D g2 = (Graphics2D) g;
              g2.setColor(Color.black);
              int fontHeight = g2.getFontMetrics().getHeight();
              int fontDesent = g2.getFontMetrics().getDescent();
              // Normalize the header color
              // he title of the report is not printed if the color of the header is different of these colors
              m_table.getTableHeader().setBackground(new java.awt.Color(204,204,204));
              m_table.getTableHeader().setForeground(new java.awt.Color(0,0,0));
              //leave room for page number
              double pageHeight = pageFormat.getImageableHeight() - fontHeight;
              double pageWidth = pageFormat.getImageableWidth();
              double tableWidth = (double) m_table.getColumnModel().getTotalColumnWidth();
              double scale = 1;
              if (tableWidth >= pageWidth) {
                   scale = pageWidth / tableWidth;
              // Get the size of the table header
              double headerHeightOnPage = m_table.getTableHeader().getHeight() * scale;
              // Get the table size on a page
              double tableWidthOnPage = tableWidth * scale;
              // Title Height
              double titleHeightOnPage = 0;
              if( m_title != null ){
                   titleHeightOnPage = ((double)m_title.getFontMetrics(m_title.getFont()).getHeight() + 40) * scale;
              // Get size of a row
              double oneRowHeight =
                   (m_table.getRowHeight() + m_table.getRowMargin()) * scale;
              int numRowsOnAPage = (int) ((pageHeight - headerHeightOnPage - titleHeightOnPage) / oneRowHeight);
              // Get number of row in a page
              double pageHeightForTable = oneRowHeight * numRowsOnAPage;
              // Get the number of page to print
              int totalNumPages =
                   (int) Math.ceil(((double) m_table.getRowCount()) / numRowsOnAPage);
              if (pageIndex >= totalNumPages) {
                   return NO_SUCH_PAGE;
              // Print the page label at bottom center
              g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
              g2.drawString(
                   "Page: " + (pageIndex + 1),
                   (int) pageWidth / 2 - 35,
                   (int) (pageHeight + fontHeight - fontDesent));
              g2.translate(0f, headerHeightOnPage + titleHeightOnPage);
              g2.translate(0f, -pageIndex * pageHeightForTable);
              //If this piece of the table is smaller than the size available,
              //clip to the appropriate bounds.
              if (pageIndex + 1 == totalNumPages) {
                   int lastRowPrinted = numRowsOnAPage * pageIndex;
                   int numRowsLeft = m_table.getRowCount() - lastRowPrinted;
                   g2.setClip(
                        0,
                        (int) (pageHeightForTable * pageIndex),
                        (int) Math.ceil(tableWidthOnPage),
                        (int) Math.ceil(oneRowHeight * numRowsLeft));
              //else clip to the entire area available.
              else {
                   g2.setClip(
                        0,
                        (int) (pageHeightForTable * pageIndex),
                        (int) Math.ceil(tableWidthOnPage),
                        (int) Math.ceil(pageHeightForTable));
              g2.scale(scale, scale);
              m_table.paint(g2);
              g2.scale(1 / scale, 1 / scale);
              g2.translate(0f, pageIndex * pageHeightForTable);
              g2.translate(0f, -headerHeightOnPage );
              g2.setClip(
                   0,
                   0,
                   (int) Math.ceil(tableWidthOnPage),
                   (int) Math.ceil(headerHeightOnPage));
              g2.scale(scale, scale);
              // Paint header at the top of the page
              m_table.getTableHeader().paint(g2);
              g2.scale(1 / scale, 1/ scale);
              g2.translate(0f, -titleHeightOnPage);
              g2.setClip(
                   0,
                   0,
                   (int) Math.ceil(tableWidthOnPage),
                   (int) Math.ceil(titleHeightOnPage));
              // Paint title
              if( m_strTitle != null ){
                   //Center
                   g2.translate((pageFormat.getImageableWidth() / 2) -
                                  (m_title.getFontMetrics(m_title.getFont()).stringWidth(m_title.getText()) / 2 ),
                                  0f );
                   g2.drawString(m_title.getText(), 0, 10);
              }else if ( m_title != null ){
                   //Center
                   g2.translate((pageFormat.getImageableWidth() / 2) -
                                  (m_title.getFontMetrics(m_title.getFont()).stringWidth(m_title.getText()) / 2 ),
                                  0f );
                   m_title.paint(g2);     
         }catch (Exception e){
              e.printStackTrace();
              return Printable.PAGE_EXISTS;
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, String title) {
         try {
              m_table = table;
              m_strTitle = title;
              m_data     = m_table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, prnJob.defaultPage());
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
         protected static PrintTable instance     = new PrintTable();
         public static int LANDSCAPE = PageFormat.LANDSCAPE;
         protected static TableModel m_data;
         protected static int m_maxNumPage           = 1;
         protected static String          m_strTitle = null;
         protected static JTable      m_table;
         protected static JLabel      m_title          = null;
         // Paper orientation
         public static int PORTRAIT = PageFormat.PORTRAIT;
         private final static String PREVIEW_LBL = "Aper�u avant impression...";
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table) {
         m_table = table;
         m_data      = table.getModel();
         PrinterJob prnJob = PrinterJob.getPrinterJob();
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             prnJob.defaultPage());
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table, PageFormat pf) {
         m_table = table;
         m_data      = table.getModel();
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             pf);
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table, String title) {
         m_table = table;
         m_data      = table.getModel();
         m_strTitle = title;
         m_title = new JLabel(title);
         PrinterJob prnJob = PrinterJob.getPrinterJob();
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             prnJob.defaultPage());
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table, String title, PageFormat pf) {
         m_table = table;
         m_data      = table.getModel();
         m_strTitle = title;
         m_title = new JLabel(title);
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             pf);
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table, JLabel title) {
         m_table = table;
         m_data      = table.getModel();
         m_title = title;
         PrinterJob prnJob = PrinterJob.getPrinterJob();
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             prnJob.defaultPage());
    * Insert the method's description here.
    * Creation date: (03-13-2002 10:12:41)
    public static void preview(JTable table, JLabel title, PageFormat pf) {
         m_table = table;
         m_data      = table.getModel();
         m_title = title;
         new PrintPreview(PrintTable.instance,
                             PREVIEW_LBL,
                             pf);
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, String title, PageFormat pf) {
         try {
              m_table = table;
              m_strTitle = title;
              m_data     = m_table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, pf);
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, String title, PageFormat pf, int orientation) {
         try {
              m_table = table;
              m_strTitle = title;
              m_data     = m_table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, prnJob.defaultPage());
              pf.setOrientation(orientation);
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, JLabel title) {
         try {
              m_table = table;
              m_title = title;
              m_data = table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, prnJob.defaultPage());
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, JLabel title, PageFormat pf) {
         try {
              m_table = table;
              m_title = title;
              m_data      = table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, pf);
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
    * Show a print dialog box
    * Call the method to print
    * @param JTable table : table to print
    * @param String title : title of the table
    public static void print(JTable table, JLabel title, PageFormat pf, int orientation) {
         try {
              m_table = table;
              m_title = title;
              m_data      = table.getModel();
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(PrintTable.instance, pf);
              // if the print job is cancelled
              if (!prnJob.printDialog())
                   return;
              pf.setOrientation(orientation);
              // print the table
              prnJob.print();
         } catch (PrinterException pe) {
              pe.printStackTrace();
              System.err.println("Printing error: " + pe.toString());
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.*;
    import java.util.*;
    import java.awt.print.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    public class PrintPreview extends JFrame
    protected int m_wPage;
    protected int m_hPage;
    protected Printable m_target;
    protected JComboBox m_cbScale;
    protected PreviewContainer m_preview;
    private String lblBtnClose           = "Fermer";
    private String lblBtnPrint           = "Imprimer...";
    protected PageFormat m_pf;
    private String[] scales                = { "10 %", "25 %", "50 %", "100 %" };
    public PrintPreview(Printable target, String title, PageFormat pf) {
         super(title);
         setSize(600, 400);
         m_target = target;
         m_pf = pf;
         JToolBar tb = new JToolBar();
         JButton bt = new JButton(this.lblBtnPrint);
         ActionListener lst = new ActionListener() {
         public void actionPerformed(ActionEvent e) {
              try {
              // Use default printer, no dialog
              PrinterJob prnJob = PrinterJob.getPrinterJob();
              prnJob.setPrintable(m_target, m_pf);
              setCursor( Cursor.getPredefinedCursor(
                   Cursor.WAIT_CURSOR));
              prnJob.print();
              setCursor( Cursor.getPredefinedCursor(
                   Cursor.DEFAULT_CURSOR));
              dispose();
              catch (PrinterException ex) {
              ex.printStackTrace();
              System.err.println("Printing error: "+ex.toString());
         bt.addActionListener(lst);
         bt.setAlignmentY(0.5f);
         bt.setMargin(new Insets(4,6,4,6));
         tb.add(bt);
         bt = new JButton(this.lblBtnClose);
         lst = new ActionListener() {
         public void actionPerformed(ActionEvent e) {
              dispose();
         bt.addActionListener(lst);
         bt.setAlignmentY(0.5f);
         bt.setMargin(new Insets(2,6,2,6));
         tb.add(bt);
         m_cbScale = new JComboBox(scales);
         lst = new ActionListener() {
         public void actionPerformed(ActionEvent e) {
              Thread runner = new Thread() {
              public void run() {
                   String str = m_cbScale.getSelectedItem().
                   toString();
                   if (str.endsWith("%"))
                   str = str.substring(0, str.length()-1);
                   str = str.trim();
                   int scale = 0;
                   try { scale = Integer.parseInt(str); }
                   catch (NumberFormatException ex) { return; }
                   int w = (int)(m_wPage*scale/100);
                   int h = (int)(m_hPage*scale/100);
                   Component[] comps = m_preview.getComponents();
                   for (int k=0; k<comps.length; k++) {
                   if (!(comps[k] instanceof PagePreview))
                        continue;
                   PagePreview pp = (PagePreview)comps[k];
                        pp.setScaledSize(w, h);
                   m_preview.doLayout();
                   m_preview.getParent().getParent().validate();
              runner.start();
         m_cbScale.addActionListener(lst);
         m_cbScale.setMaximumSize(m_cbScale.getPreferredSize());
         m_cbScale.setEditable(true);
         tb.addSeparator();
         tb.add(m_cbScale);
         getContentPane().add(tb, BorderLayout.NORTH);
         m_preview = new PreviewContainer();
         PrinterJob prnJob = PrinterJob.getPrinterJob();
         PageFormat pageFormat = pf;
         if (pageFormat.getHeight()==0 || pageFormat.getWidth()==0) {
         System.err.println("Unable to determine default page size");
              return;
         m_wPage = (int)(pageFormat.getWidth());
         m_hPage = (int)(pageFormat.getHeight());
         int scale = 10;
         int w = (int)(m_wPage*scale/100);
         int h = (int)(m_hPage*scale/100);
         int pageIndex = 0;
         try {
         while (true) {
              BufferedImage img = new BufferedImage(m_wPage,
              m_hPage, BufferedImage.TYPE_INT_RGB);
              Graphics g = img.getGraphics();
              g.setColor(Color.white);
              g.fillRect(0, 0, m_wPage, m_hPage);
              if (target.print(g, pageFormat, pageIndex) !=
              Printable.PAGE_EXISTS)
              break;
              PagePreview pp = new PagePreview(w, h, img);
              m_preview.add(pp);
              pageIndex++;
         catch (PrinterException e) {
         e.printStackTrace();
         System.err.println("Printing error: "+e.toString());
         JScrollPane ps = new JScrollPane(m_preview);
         getContentPane().add(ps, BorderLayout.CENTER);
         setDefaultCloseOperation(DISPOSE_ON_CLOSE);
         setVisible(true);
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.border.*;
    * Insert the type's description here.
    * Creation date: (03-12-2002 14:17:45)
    * @author: Alexandre Spain
    public class PreviewContainer extends JPanel {
         protected int H_GAP = 16;
         protected int V_GAP = 10;
    * PreviewContainer constructor comment.
    public PreviewContainer() {
         super();
    public void doLayout() {
         Insets ins = getInsets();
         int x = ins.left + H_GAP;
         int y = ins.top + V_GAP;
         int n = getComponentCount();
         if (n == 0)
              return;
         Component comp = getComponent(0);
         Dimension dc = comp.getPreferredSize();
         int w = dc.width;
         int h = dc.height;
         Dimension dp = getParent().getSize();
         int nCol = Math.max((dp.width-H_GAP)/(w+H_GAP), 1);
         int nRow = n/nCol;
         if (nRow*nCol < n)
              nRow++;
         int index = 0;
         for (int k = 0; k<nRow; k++) {
              for (int m = 0; m<nCol; m++) {
                   if (index >= n)
                        return;
                   comp = getComponent(index++);
                   comp.setBounds(x, y, w, h);
                   x += w+H_GAP;
              y += h+V_GAP;
              x = ins.left + H_GAP;
    public Dimension getMaximumSize() {
         return getPreferredSize();
    public Dimension getMinimumSize() {
         return getPreferredSize();
    public Dimension getPreferredSize() {
         int n = getComponentCount();
         if (n == 0)
              return new Dimension(H_GAP, V_GAP);
         Component comp = getComponent(0);
         Dimension dc = comp.getPreferredSize();
         int w = dc.width;
         int h = dc.height;
         Dimension dp = getParent().getSize();
         int nCol = Math.max((dp.width-H_GAP)/(w+H_GAP), 1);
         int nRow = n/nCol;
         if (nRow*nCol < n)
              nRow++;
         int ww = nCol*(w+H_GAP) + H_GAP;
         int hh = nRow*(h+V_GAP) + V_GAP;
         Insets ins = getInsets();
         return new Dimension(ww+ins.left+ins.right,
                                  hh+ins.top+ins.bottom);
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.border.*;
    * Insert the type's description here.
    * Creation date: (03-12-2002 14:17:06)
    * @author: Alexandre Spain
    public class PagePreview extends JPanel {
         protected int m_w;
         protected int m_h;
         protected Image m_source;
         protected Image m_img;
    * PagePreview constructor comment.
    * @param target java.awt.print.Printable
    public PagePreview(int w, int h, Image source) {
         m_w = w;
         m_h = h;
         m_source= source;
         m_img = m_source.getScaledInstance(m_w, m_h,
              Image.SCALE_SMOOTH);
         m_img.flush();
         setBackground(Color.white);
         setBorder(new MatteBorder(1, 1, 2, 2, Color.black));
    public Dimension getMaximumSize() {
         return getPreferredSize();
    public Dimension getMinimumSize() {
         return getPreferredSize();
    public Dimension getPreferredSize() {
         Insets ins = getInsets();
         return new Dimension(m_w+ins.left+ins.right,
                                  m_h+ins.top+ins.bottom);
    public void paint(Graphics g) {
         g.setColor(getBackground());
         g.fillRect(0, 0, getWidth(), getHeight());
         g.drawImage(m_img, 0, 0, this);
         paintBorder(g);
    public void setScaledSize(int w, int h) {
         m_w = w;
         m_h = h;
         m_img = m_source.getScaledInstance(m_w, m_h,
         Image.SCALE_SMOOTH);
         repaint();

  • Print JTable with row headers

    I am using the fancy new printing capablities in java 1.5 to print my JTable and wow is it ever slick!
    PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
    set.add(OrientationRequested.LANDSCAPE);
    this.matrixJTable.print(JTable.PrintMode.NORMAL, null, null, true, set, false);Its just that easy. Way to go sun!
    The one problem that I am encountering is that my row headers don't print. The problem is that JTables don't support row headers, you have to use a JScrollPane for that.
    I need a way to print my JTable so that the row headers show up in the printout... and hopefully still use the warm and fuzzy new printing capabilities of JTable printing in java 1.5.
    (ps/ Isn't it time to add row header support to JTables?)

    The problem is that JTables don't support row headers, you have to use a JScrollPane for that.Well technically JTable's don't really support column headers either. It is a seperate component (JTableHeader). A JTable will automatically add its table header to the table header area of a JScrollPane. (but you don't have to use a jscrollpane to see the column headers, it is just the quickest and easiest way).
    Really shouldn't be hard to implement a row header and manually add it to the scroll panes row header area or use a BorderLayout and put your row header in the WEST and put your table in the CENTER if you don't want a scroll pane.
    Of course this won't help you with your printing issue.

  • Print JTable with column heading

    Hi,
    I'm very new to this JTable. I'm try to print a Jtable using the print() function (from JDK 1.5)
    JTable.print(JTable.PrintMode.FIT_WIDTH, new MessageFormat(
    _tabledata.getTitle() ),
    new MessageFormat("Page {0,number}"));
    The problem I have is that some time it print and other time it doens't print. Also, if it doesn't print, then the program become very slow or not respond. Is that the probelm with the new JDK or am I doing something wrong?
    Thanks for you help.

    Don't rely on JTable.print() methods too much.
    Sadly Sun didn't think anyone would need to print anything from java so support was added late and half heartedly (programmers hate printing stuff)
    If you are new to java you need to focus on something simpler than printing documents; unfortunatly printing is a tedious burdonsome task for experreineced developers
    for example: learn how to output your data from a table into an HTML formate/file; you can build beautiful reports/printouts easily and view them in java components easily but you will probably want to print them from a browser.
    Even if you find a class or two to help with your printing efforts on the net you will find you need to know many other generic complicated aspects of java to continue
    Sean

  • Print JTable with multi line header

    I need to print a JTable with multi line header, I want to know if I can use the method jTable.print(int, MessajeFormat, MessageFormat) by manipulation of the MessageFormat. How I can manipulate it?
    Otherwise, How I can print this?

    hi again,
    To print pdf in a swing application you don't need servlet.jar.
    You'll only need itext.jar and a printer connected to your pc.
    Download the iText source code and unzip it. See the following classes:
    com.lowagie.tools.LPR and com.lowagie.tools.BuildTutorial. This latter is the main class of a swing tool that you can run.
    Silent Print:
    You have only to embed this javascript code in your pdf:
    writer.addJavaScript("this.print(false);", false);
                        document.add(new Chunk("Silent Auto Print"));Then, you have to send the document to the printer.
    Google : java print pdf
    http://forum.java.sun.com/thread.jspa?threadID=523898 or
    http://www.exampledepot.com/egs/javax.print/pkg.html for printing task.
    Under unix system, I used this:
                           String PRINTER = ...;
                   try {
                        String cmd = "lp -d " + PRINTER + " " + PDF_PATH;
                        Runtime.getRuntime().exec(new String[] { "sh", "-c", cmd });
                   } catch (Exception e) {
                                 //handle the exception
                                 e.printStackTrace();
                   }hth

  • How to print jTable with custom header and footer....

    Hello all,
    I'm trying to print a jTable with custom header and footer.But
    jTable1.print(PrintMode,headerFormat,footerFormat,showPrintDialog,attr,interactive)
    does not allow multi line header and footer. I read in a chat that we can make custom header and footer and wrap the printable with that of the jTable. How can we do that..
    Here's the instruction on the chat...
    Shannon Hickey: While the default Header and Footer support in the JTable printing won't do exactly what you're looking for, there is a straight-forward approach. You can turn off the default header/footer and then wrap JTable's printable inside another Printable. This wrapper printable would then render your custom data, and then adjust the size given to the wrapped printable
    But how can i wrap the jTable's Printable with the custom header and footer.
    Thanks in advance,

    I also once hoped for an easy way to modify a table's header and footer, but found no way.
    Yet it is possible.

  • Print jTable with a header and footer panel

    Hi Folks,
    I'm currently at a sticking point in a project I'm playing around with. I have a data set of around 300 objects that i'd like printed out in a table. Now, I've gotten the display part down without a hitch but printing the data as well as a header panel and footer panel has been eluding me. I'd basically like something like this...
    Name: some name Order date: some date
    Address: some address Shipped To: some address
    somewhere Some city, some state, etc
    in some city
    Date | Title | Etc | Etc | Etc
    date1 title1 5 $3.00 $15.00
    date1 title1 5 $3.00 $15.00
    date2 title1 5 $3.00 $15.00
    date2 title1 5 $3.00 $15.00
    Total purchases: $60.00
    Total Items: 20
    # of Orders: 2
    Am I barking up the wrong tree by making the first and third sections panels and the second section a table? If not, how the heck do I accomplish this? Most of the time the table has been multiple pages as well - I only need section one on the first page and section three on the last page, but whatever is easiest really.
    My current approach has been basically to make a custom printables, print the first section, figure out how high it was, print the second section and hope for the best, but the third would never show up because it'd never go over two pages.
    Any help would be very much appreciated.
    Thanks,
    Stephen
    Edited by: stephenliberty on May 7, 2009 9:11 AM - more specific subject

    I suppose as a quick update, this is as far as I've gotten and will likely get-
    public class PrintForm extends JFrame implements Printable{
        JComponent headerPanelForPrint;
        JComponent footerPanelForPrint;
        JTable dataTableForPrint;
        public void setPieces(JComponent header, JTable table, JComponent footer){
            this.headerPanelForPrint = header;
            this.footerPanelForPrint = footer;
            this.dataTableForPrint = table;
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            graphics.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());
            TableFormat tableFormat;
            if(pageIndex>0){
                tableFormat = new TableFormat(0, footerPanelForPrint.getHeight());
            } else {
                headerPanelForPrint.printAll(graphics);
                tableFormat = new TableFormat(headerPanelForPrint.getHeight(), footerPanelForPrint.getHeight());
            MessageFormat footer = new MessageFormat("Page - {0}");
            Printable table = dataTableForPrint.getPrintable(PrintMode.FIT_WIDTH, null, footer);
            int printme = table.print(graphics, tableFormat, pageIndex);
            if(printme == table.NO_SUCH_PAGE){ return table.NO_SUCH_PAGE; }
            return Printable.PAGE_EXISTS;
    class TableFormat extends PageFormat {
        double footerHeight;
        double headerHeight;
        public TableFormat(double headerHeight, double footerHeight){
            this.headerHeight = headerHeight;
            this.footerHeight = footerHeight;
        @Override
        public double getImageableHeight() {
            return super.getImageableHeight() - ( this.footerHeight + this.headerHeight );
        @Override
        public double getHeight() {
            return super.getImageableHeight() - ( this.footerHeight + this.headerHeight);
        @Override
        public double getImageableX() {
            return 0;
        @Override
        public double getImageableY() {
            return this.headerHeight;
    }It works very well with just a header and the table, but I still have not been able to get a footer to show up in the appropriate spot or (preferably) on the last page.
    Edited by: stephenliberty on May 8, 2009 12:29 PM

  • Print a JTable with several Header and Footers

    Hi everybody,
    my name is Lothar and I come from Germany. My english is not very well, but I hope you understand me an my problem.
    I want to print a JTable, but I want to print a header with several headers and footers.
    For example:
    h3. Header
    h5. 1. Subtitle
    h5. 2. Subtitle
    Table
    h5. 3. Subtitle
    h5. Footer
    But, I do not know how I can do that. Can anybody tell me, how I can solve my problem. Please, explain for a newbie because I have learned Java since two months ;)
    Here the code:
    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import java.util.Date;
    import javax.swing.*;
    public class Beispiel extends JFrame implements ActionListener {
        private JTable table;
        public static void main(String[] args) {
            Beispiel tl = new Beispiel();
            tl.setVisible(true);
            tl.pack();
        public Beispiel() {
            setLayout(new BorderLayout());
            // DruckButton
            JButton print = new JButton("Print");
            add(print, BorderLayout.SOUTH);
            print.addActionListener(this);
            // Tabelle
            add(new JScrollPane(createTable()), BorderLayout.CENTER);
            // schlie&szlig;t das Frame
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        public JTable createTable() {
            // titel
            String[] title = new String[] { "Datum", "Von", "Bis",
                    "Dauerinsgesamt", "Bemerkung" };
            // daten
            String[][] data = new String[][] { { "", "", "", "", "" },
            table = new JTable(data, title);
            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            return table;
        public void actionPerformed(ActionEvent e1) {
            MessageFormat header = new MessageFormat("Header");
            MessageFormat footer = new MessageFormat("Footer");
            try {
                table.print(JTable.PrintMode.FIT_WIDTH, header, footer);
            } catch (Exception e2) {
                System.err.format("Cannot print %s%n", e2.getMessage());
    }

    Nobody?
    Can nobody solve my problem?

  • How can I print a JTable with varying sized rows?

    How can I print a JTable with varying sized rows?
    I am using java 1.5, and have made a cell renderer to display multiple lines in rows and it works well, however when I use the new print method it doesn't separate the cells onto the next page, it cuts them and will print the rest of the row on the next page. Does anyone know how I might go about making this happen?
    cheers

    I finally found out the reason, The column heights were being set through my renderer. If I hadn't viewed them in the scrollpane the row heights were set to the default height of 16 therefore when the print method was called it clipped all the rows wrong, what is weird though is that the row height printed out correctly but the clipping area was set wrong because it was getting the default value of 16 from rowHeight(row).

  • Is it possible to print JTable and custom JPanel on the same page?

    Hello everybody!
    I have a custom panel extending JPanel and implementing Printable.
    I am using paint() method to draw some graphics on it's content pane. I would like to print it, but first I would like to add a JTable at the bottom of my panel. Printing just the panel goes well. No problems with that.
    I was also able to add a JTable to the bottom of JFrame, which contains my panel.
    But how can I print those two components on one page?

    Hi, thanks for your answer, but I thought about that earlier and that doesn't work as well... or mybe I'm doing something wrong. Here is the sample code:
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.print.PageFormat;
    import java.awt.print.Printable;
    import java.awt.print.PrinterException;
    import java.awt.print.PrinterJob;
    import javax.print.attribute.HashPrintRequestAttributeSet;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    public class ReportFrame extends JFrame implements Printable {
         private static final long serialVersionUID = -8291124097290245799L;
         private MyPanel rp;
         private JTable reportTable;
         private HashPrintRequestAttributeSet attributes;
         public ReportFrame() {
              rp = new MyPanel();
              String[] columnNames = { "Column1", "Column2", "Column3" };
              String[][] values = { { "Value1", "Value2", "Value3" }, { "Value4", "Value5", "Value6" }, { "Value7", "Value8", "Value9" } };
              reportTable = new JTable(values, columnNames);
              add(rp, BorderLayout.CENTER);
              add(reportTable, BorderLayout.SOUTH);
              setTitle("Printing example");
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              setPreferredSize(new Dimension(700, 700));
              pack();
              setVisible(true);
         @Override
         public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
              if (pageIndex >= 1)
                   return Printable.NO_SUCH_PAGE;
              Graphics2D g2D = (Graphics2D) graphics;
              g2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
              return Printable.PAGE_EXISTS;
         public static void main(String[] args) {
              new ReportFrame().printer();
         class MyPanel extends JPanel implements Printable {
              private static final long serialVersionUID = -2214177603101440610L;
              @Override
              public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
                   if (pageIndex >= 1)
                        return Printable.NO_SUCH_PAGE;
                   Graphics2D g2D = (Graphics2D) graphics;
                   g2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
                   return Printable.PAGE_EXISTS;
              @Override
              public void paint(Graphics g) {
                   super.paintComponent(g);
                   Graphics2D g2D = (Graphics2D) g;
                   int x = 0, y = 0, width = 70, height = 70;
                   for (int i = 0; i < 50; i++) {
                        g2D.drawOval(x + i * 10, y + i * 10, width, height);
         public void printer() {
              try {
                   attributes = new HashPrintRequestAttributeSet();
                   PrinterJob job = PrinterJob.getPrinterJob();
                   job.setPrintable(this);
                   if (job.printDialog(attributes))
                        job.print(attributes);
              } catch (PrinterException e) {
                   JOptionPane.showMessageDialog(this, e);
    }UPDATE:
    I've managed to get this to work, by calling 2 methods inside the outer frame's print method (lines 78 and 79)
    Those two methods are:
    rp.paint(g2D);
    reportTable.paint(g2D);but still it is not the way I would like it to be.
    First of all both the ReportPanel and ReportTable graphics are printed with the upper-left corner located in the upper-left corner of the JFrame and the first one is covering the second.
    Secondly, I would like to rather implemet the robust JTable's print method somehow, because it has some neat features like multipage printing, headers & footers. But I have no idea how to add my own graphics to the JTables print method, so they will appear above the JTable. Maybe someone knows the answer?
    Thanks a lot
    UPDATE2:
    I was googling nearly all day in search of an answer, but with no success. I don't think it's possible to print JTable using it's print() method together with other components, so I will have to think of something else i guess...
    Edited by: Adalbert23 on Nov 22, 2007 2:49 PM

  • JTable with JCheckbox problems

    Ok so I have a couple of questions. I have a JTable with a column represented as a checkbox.
    1. If I put the checkbox column as the first in the table, the rest of the cells are blank/null. Any idea what the reason is?
    2. What is the best workaround to having draggable columns, meaning icons/checkboxes don't render if you move the columns around?
    3. Does anyone have some links to good resources on JTables and things like custom components in them. I have googled but don't get many good links so would appreciate any help
    Code snippet as follows:
    public class ClobberTableCellRenderer implements TableCellRenderer
    private JPanel renderPanel = new JPanel(new BorderLayout());
    private JLabel renderLbl = new JLabel("");
    private JCheckBox checked = new JCheckBox();
    private Icon successIcon;
    private Icon errorIcon;
    public Component getTableCellRendererComponent(JTable table,
    Object value,
    boolean isSelected,
    boolean hasFocus,
    int row,
    int column)
    String columnName = table.getModel().getColumnName(column);
    if (value == null)
    return null;
    else if ("Status".equals(columnName) && "ok".equals(value))
    renderLbl.setIcon(successIcon);
    renderLbl.setText("");
    renderPanel.remove(checked);
    else if ("Status".equals(columnName) && "error".equals(value))
    renderLbl.setIcon(errorIcon);
    renderLbl.setText("");
    renderPanel.remove(checked);
    else if ("Active".equals(columnName))
    renderLbl.setText("");
    renderPanel.add(checked);
    renderPanel.setBackground(Color.white);
    else
    renderLbl.setHorizontalAlignment(value instanceof Date || value instanceof Number ? JLabel.RIGHT : JLabel.LEFT);
    renderLbl.setIcon(null);
    renderLbl.setText(value instanceof Date ? df.format((Date)value) : value.toString());
    renderLbl.setToolTipText(null);
    renderPanel.setToolTipText(null);
    renderPanel.remove(checked);
    if (isSelected)
    renderPanel.setBackground((Color)UIManager.getDefaults().get("Table.selectionBackground"));
    else
    renderPanel.setBackground((Color)UIManager.getDefaults().get("Table.background"));
    return renderPanel;
    }

    Hi :) I have also worked on JTables and JCheckBoxes before. This article
    helped me a lot: http://www-128.ibm.com/developerworks/java/library/j-jtable/

  • JTable with JComboBox/JSpinner problem

    The following code has a JTable with 2 columns.The lst column has JComboBoxes, the 2nd column has JSpinners.I want to set the spinner range of values based on the selection of JComboBox. The JComboBox selections are "small" and "large". For "small" the spinner should range from 0..49, for "large" from 50..99. When a selection is made, MyTable.itemStateChanged() is called, which in turn calls SpinnerEditor.setValueRange(). This sets an array with the desired values and then sets the model with this array. However, it sets the range not only for the row in which the combo box was clicked, but all rows.
    So in MyTable.setCellComponents(), there is this:
    spinnerEditor = new SpinnerEditor(this, defaultTableModel);
    modelColumn.setCellEditor(spinnerEditor);
    If the table has n rows, are n SpinnerEditors created, or just 1?
    If 1, do n need to be created and if so, how?
    public class MyTable extends JTable implements ItemListener {
         private DefaultTableModel defaultTableModel;
         private Vector<Object> columnNameVector;
         private JComboBox jComboBox;
         private SpinnerEditor spinnerEditor;
         private final int COMBO_BOX_COLUMN = 0;
         final static int SPINNER_COLUMN = 1;
         public static String SMALL = "Small";
         public String LARGE = "Large";
         private final String[] SMALL_LARGE = {
                   SMALL,
                   LARGE };
         public MyTable(String name, Object[][] variableNameArray, Object[] columnNameArray) {
              columnNameVector = new Vector<Object>();
              // need column names in order to make copy of table model
              for (Object object : columnNameArray) {
                   columnNameVector.add(object);
              defaultTableModel = new DefaultTableModel(variableNameArray, columnNameArray);
              this.setModel(defaultTableModel)     ;
              setCellComponents();
              setListeners();
         private void setCellComponents() {
              // combo box column -----------------------------------------------
              TableColumn modelColumn = this.getColumnModel().getColumn(COMBO_BOX_COLUMN);
              jComboBox = new JComboBox(SMALL_LARGE);
              // set default values
              for (int row = 0; row < defaultTableModel.getRowCount(); row++) {
                   defaultTableModel.setValueAt(SMALL_LARGE[0], row, COMBO_BOX_COLUMN);
              modelColumn.setCellEditor(new DefaultCellEditor(jComboBox));
              DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
              renderer.setToolTipText("Click for small/large"); // tooltip
              modelColumn.setCellRenderer(renderer);
              // index spinner column ------------------------------------------------------------
              modelColumn = this.getColumnModel().getColumn(SPINNER_COLUMN);
              spinnerEditor = new SpinnerEditor(this, defaultTableModel);
              modelColumn.setCellEditor(spinnerEditor);
              renderer = new DefaultTableCellRenderer();
              renderer.setToolTipText("Click for index value"); // tooltip
              modelColumn.setCellRenderer(renderer);
         private void setListeners() {
              jComboBox.addItemListener(this);
         @Override
         public void itemStateChanged(ItemEvent event) {
              // set spinner values depending on small or large
              String smallOrLarge = (String)event.getItem();
              if (this.getEditingRow() != -1 && this.getEditingColumn() != -1) {
                   spinnerEditor.setValueRange(smallOrLarge);
         public static void main(String[] args) {
              try{
                   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
              catch (Exception e){
                   e.printStackTrace();
              String[] columnNameArray = {"JComboBox", "JSpinner"};
              Object[][]  dataArray = {
                        {"", "0"},
                        {"", "0"},
                        {"", "0"},
              final MyTable myTable = new MyTable("called from main", dataArray, columnNameArray);
              final JFrame frame = new JFrame();
              frame.getContentPane().add(new JScrollPane(myTable));
              frame.setTitle("My Table");
              frame.setPreferredSize(new Dimension(200, 125));
              frame.addWindowListener(new WindowAdapter(){
                   @Override
                   public void windowClosing(WindowEvent e) {
              frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
              frame.setLocation(800, 400);
              frame.pack();
              frame.setVisible(true);
    public class SpinnerEditor extends AbstractCellEditor implements TableCellEditor {
         private JComponent parent;
         private DefaultTableModel defaultTableModel;
         private final JSpinner spinner = new JSpinner();
         private String[] spinValues;
         private int row;
         private int column;
         public SpinnerEditor(JTable parent, DefaultTableModel defaultTableModel ) {
              super();
              this.parent = parent;
              this.defaultTableModel = defaultTableModel;
              setValueRange(MyTable.SMALL);
              // update every time spinner is incremented or decremented
              spinner.addChangeListener(new ChangeListener(){
                   public void stateChanged(ChangeEvent e) {
                        String value = (String) spinner.getValue();
                        System.out.println ("SpinnerEditor.stateChanged(): " + value);
                        setValue(value);
         private void setValue(String value) {
              // save to equation string
              System.out.println ("SpinnerEditor.setValue(): " + value + " at (" + row + ", " + MyTable.SPINNER_COLUMN + ")");
              ((JTable) parent).setValueAt(spinner.getValue(), this.row, this.column);
         @Override
         public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)      {
              System.out.println ("SpinnerEditor.getTableCellEditorComponent(): row: " + row + "\tcolumn: " + column);
              System.out.println ("SpinnerEditor.getTableCellEditorComponent(): value: " + value);
              this.row = row;
              this.column = column;
              return spinner;
         @Override
         public boolean isCellEditable(EventObject evt) {
              return true;
         // Returns the spinners current value.
         @Override
         public Object getCellEditorValue() {
              return spinner.getValue();
         @Override
         public boolean stopCellEditing() {
              System.out.println("SpinnerEditor.stopCellEditing(): spinner: " + spinner.getValue() + " at (" + this.row + ", " + this.column + ")");
              ((JTable) parent).setValueAt(spinner.getValue(), this.row, this.column);
              return true;
         public void setValueRange(String smallOrLarge) {
              System.out.println ("SpinnerEditor.setValueRange for " + smallOrLarge);
              final int ARRAY_SIZE = 50;
              if (MyTable.SMALL.equals(smallOrLarge)) {
                   final int MIN_SPIN_VALUE = 0;               
                   final int MAX_SPIN_VALUE = 49;
                   //System.out.println ("SpinnerEditor.setValueRange(): [" + MIN_SPIN_VALUE + ".." +  MAX_SPIN_VALUE + "]");
                   spinValues = new String[ARRAY_SIZE];
                   for (int i = MIN_SPIN_VALUE; i <= MAX_SPIN_VALUE; i++) {
                        spinValues[i] = new String(Integer.toString(i));
              else { // large
                   final int MIN_SPIN_VALUE = 50;               
                   final int MAX_SPIN_VALUE = 99;
                   //System.out.println ("SpinnerEditor.setValueRange(): [" + MIN_SPIN_VALUE + ".." +  MAX_SPIN_VALUE + "]");
                   spinValues = new String[ARRAY_SIZE];
                   for (int i = 0; i <ARRAY_SIZE; i++) {
                        spinValues[i] = new String(Integer.toString(MIN_SPIN_VALUE + i));
                   //for (int i = 0; i <ARRAY_SIZE; i++) {
                   //     System.out.println ("spinValues[" + i + "] = " + spinValues);
              System.out.println ("SpinnerEditor.setValueRange(): [" + spinValues[0] + ".." + spinValues[ARRAY_SIZE-1] + "]");
              // set model
              spinner.setModel(new SpinnerListModel(java.util.Arrays.asList(spinValues)));

    However, it sets the range not only for the row in which the combo box was clicked, but all rows. Yes, because a single editor is used by the column.
    One solution is to create two editors, then you override the getCellEditor(...) method to return the appropriated editor. Something like:
    If (column == ?)
        if (smallOrLarge)
          return the small or large spinner editor
        else
           return the large spinner editor
    else
        return super.getCellEditor(...);

  • Image in header of print (JTable)

    Hello,
    I have a question about printing a JTable. I use the following code which works well but I want to extend my print with a image (a logo) in the header of every page. What is the best way to achieve this?
    My second question is how I can change the font size of the header?
    Thanks for your reply.
    Regards Stefan.
    MessageFormat header = new MessageFormat("Test");
    MessageFormat footer = new MessageFormat("Page - {0}");
    try {
        if (!myTable.print(JTable.PrintMode.FIT_WIDTH
    , header, footer, true, null, true)) {
            System.err.println("User cancelled printing");
    } catch (java.awt.print.PrinterException e) {
        System.err.format("Cannot print %s%n", e.getMessage());
    }     

    The API provided by the JTable class is described as simple, and indeed it is. To obtain more complex printing, you need to use the JTable.getPrintable method and do some extra work to get the results desired.
    There are also several third party codes you can try. Do a search on google to search what you find
    ICE

Maybe you are looking for