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.

Similar Messages

  • 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 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 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?

  • 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

  • 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 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.

  • JTable - Groupable/Multiline Header

    Hi Everybody,
    I found this code to create a groupable/multiline header for a JTable. It seems to be working fine with JDK 1.1 and we are using 1.4 now. I keep getting 2 errors with the GroupableTableHeaderUI class and has been busy the whole weekend trying to fix it, with no success. Can someone please help? Thanks. Here is the code:
    * |-----------------------------------------------------|
    * | | Name | Language |
    * | |-----------------|--------------------------|
    * | SNo. | | | | Others |
    * | | 1 | 2 | Native |-----------------|
    * | | | | | 2 | 3 |
    * |-----------------------------------------------------|
    * | | | | | | |
    package tableheader;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import swing.table.*;
    public class GroupableHeaderExample extends JFrame {
    GroupableHeaderExample() {
    super( "Groupable Header Example" );
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][]{
    {"119","foo","bar","ja","ko","zh"},
    {"911","bar","foo","en","fr","pt"}},
    new Object[]{"SNo.","1","2","Native","2","3"});
    JTable table = new JTable( dm ) {
    protected JTableHeader createDefaultTableHeader() {
         return new GroupableTableHeader(columnModel);
    TableColumnModel cm = table.getColumnModel();
    ColumnGroup g_name = new ColumnGroup("Name");
    g_name.add(cm.getColumn(1));
    g_name.add(cm.getColumn(2));
    ColumnGroup g_lang = new ColumnGroup("Language");
    g_lang.add(cm.getColumn(3));
    ColumnGroup g_other = new ColumnGroup("Others");
    g_other.add(cm.getColumn(4));
    g_other.add(cm.getColumn(5));
    g_lang.add(g_other);
    GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
    header.addColumnGroup(g_name);
    header.addColumnGroup(g_lang);
    JScrollPane scroll = new JScrollPane( table );
    getContentPane().add( scroll );
    setSize( 400, 120 );
    public static void main(String[] args) {
    GroupableHeaderExample frame = new GroupableHeaderExample();
    frame.addWindowListener( new WindowAdapter() {
    public void windowClosing( WindowEvent e ) {
         System.exit(0);
    frame.setVisible(true);
    package swing.table;
    import java.util.*;
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    public class GroupableTableHeader extends JTableHeader {
    private static final String uiClassID = "GroupableTableHeaderUI";
    protected Vector columnGroups = null;
    public GroupableTableHeader(TableColumnModel model) {
    super(model);
    setUI(new GroupableTableHeaderUI());
    setReorderingAllowed(false);
    public void setReorderingAllowed(boolean b) {
    reorderingAllowed = false;
    public void addColumnGroup(ColumnGroup g) {
    if (columnGroups == null) {
    columnGroups = new Vector();
    columnGroups.addElement(g);
    public Enumeration getColumnGroups(TableColumn col) {
    if (columnGroups == null) return null;
    Enumeration enum = columnGroups.elements();
    while (enum.hasMoreElements()) {
    ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
    Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
    if (v_ret != null) {
         return v_ret.elements();
    return null;
    public void setColumnMargin() {
    if (columnGroups == null) return;
    int columnMargin = getColumnModel().getColumnMargin();
    Enumeration enum = columnGroups.elements();
    while (enum.hasMoreElements()) {
    ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
    cGroup.setColumnMargin(columnMargin);
    package swing.table;
    import java.util.*;
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import javax.swing.plaf.basic.*;
    public class GroupableTableHeaderUI extends BasicTableHeaderUI {
    public void paint(Graphics g, JComponent c) {
    Rectangle clipBounds = g.getClipBounds();
    if (header.getColumnModel() == null) return;
    ((GroupableTableHeader)header).setColumnMargin();
    int column = 0;
    Dimension size = header.getSize();
    Rectangle cellRect = new Rectangle(0, 0, size.width, size.height);
    Hashtable h = new Hashtable();
    int columnMargin = header.getColumnModel().getColumnMargin();
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
    cellRect.height = size.height;
    cellRect.y = 0;
    TableColumn aColumn = (TableColumn)enumeration.nextElement();
    Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
    if (cGroups != null) {
    int groupHeight = 0;
    while (cGroups.hasMoreElements()) {
    ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
    Rectangle groupRect = (Rectangle)h.get(cGroup);
    if (groupRect == null) {
    groupRect = new Rectangle(cellRect);
    Dimension d = cGroup.getSize(header.getTable());
    groupRect.width = d.width;
    groupRect.height = d.height;
    h.put(cGroup, groupRect);
    paintCell(g, groupRect, cGroup);
    groupHeight += groupRect.height;
    cellRect.height = size.height - groupHeight;
    cellRect.y = groupHeight;
    cellRect.width = aColumn.getWidth() + columnMargin;
    if (cellRect.intersects(clipBounds)) {
    paintCell(g, cellRect, column);
    cellRect.x += cellRect.width;
    column++;
    private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
    TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
    TableCellRenderer renderer = aColumn.getHeaderRenderer();
    Component component = renderer.getTableCellRendererComponent(
    header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
    rendererPane.add(component);
    rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
                        cellRect.width, cellRect.height, true);
    private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
    TableCellRenderer renderer = cGroup.getHeaderRenderer();
    Component component = renderer.getTableCellRendererComponent(
    header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
    rendererPane.add(component);
    rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
                        cellRect.width, cellRect.height, true);
    private int getHeaderHeight() {
    int height = 0;
    TableColumnModel columnModel = header.getColumnModel();
    for(int column = 0; column < columnModel.getColumnCount(); column++) {
    TableColumn aColumn = columnModel.getColumn(column);
    TableCellRenderer renderer = aColumn.getHeaderRenderer();
    Component comp = renderer.getTableCellRendererComponent(
    header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
    int cHeight = comp.getPreferredSize().height;
    Enumeration enum = ((GroupableTableHeader)header).getColumnGroups(aColumn);
    if (enum != null) {
    while (enum.hasMoreElements()) {
    ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
    cHeight += cGroup.getSize(header.getTable()).height;
    height = Math.max(height, cHeight);
    return height;
    private Dimension createHeaderSize(long width) {
    TableColumnModel columnModel = header.getColumnModel();
    width += columnModel.getColumnMargin() * columnModel.getColumnCount();
    if (width > Integer.MAX_VALUE) {
    width = Integer.MAX_VALUE;
    return new Dimension((int)width, getHeaderHeight());
    public Dimension getPreferredSize(JComponent c) {
    long width = 0;
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
    TableColumn aColumn = (TableColumn)enumeration.nextElement();
    width = width + aColumn.getPreferredWidth();
    return createHeaderSize(width);
    package swing.table;
    import java.util.*;
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    public class ColumnGroup {
    protected TableCellRenderer renderer;
    protected Vector v;
    protected String text;
    protected int margin=0;
    public ColumnGroup(String text) {
    this(null,text);
    public ColumnGroup(TableCellRenderer renderer,String text) {
    if (renderer == null) {
    this.renderer = new DefaultTableCellRenderer() {
         public Component getTableCellRendererComponent(JTable table, Object value,
    boolean isSelected, boolean hasFocus, int row, int column) {
         JTableHeader header = table.getTableHeader();
         if (header != null) {
         setForeground(header.getForeground());
         setBackground(header.getBackground());
         setFont(header.getFont());
    setHorizontalAlignment(JLabel.CENTER);
    setText((value == null) ? "" : value.toString());
         setBorder(UIManager.getBorder("TableHeader.cellBorder"));
         return this;
    } else {
    this.renderer = renderer;
    this.text = text;
    v = new Vector();
    * @param obj TableColumn or ColumnGroup
    public void add(Object obj) {
    if (obj == null) { return; }
    v.addElement(obj);
    * @param c TableColumn
    * @param v ColumnGroups
    public Vector getColumnGroups(TableColumn c, Vector g) {
    g.addElement(this);
    if (v.contains(c)) return g;
    Enumeration enum = v.elements();
    while (enum.hasMoreElements()) {
    Object obj = enum.nextElement();
    if (obj instanceof ColumnGroup) {
    Vector groups =
    (Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
    if (groups != null) return groups;
    return null;
    public TableCellRenderer getHeaderRenderer() {
    return renderer;
    public void setHeaderRenderer(TableCellRenderer renderer) {
    if (renderer != null) {
    this.renderer = renderer;
    public Object getHeaderValue() {
    return text;
    public Dimension getSize(JTable table) {
    Component comp = renderer.getTableCellRendererComponent(
    table, getHeaderValue(), false, false,-1, -1);
    int height = comp.getPreferredSize().height;
    int width = 0;
    Enumeration enum = v.elements();
    while (enum.hasMoreElements()) {
    Object obj = enum.nextElement();
    if (obj instanceof TableColumn) {
    TableColumn aColumn = (TableColumn)obj;
    width += aColumn.getWidth();
    width += margin;
    } else {
    width += ((ColumnGroup)obj).getSize(table).width;
    return new Dimension(width, height);
    public void setColumnMargin(int margin) {
    this.margin = margin;
    Enumeration enum = v.elements();
    while (enum.hasMoreElements()) {
    Object obj = enum.nextElement();
    if (obj instanceof ColumnGroup) {
    ((ColumnGroup)obj).setColumnMargin(margin);

    in GroupableTableHeaderUI class replace "aColumn.getHeaderRenderer();" by "header.getDefaultRenderer ();" and try again..
    this should solve ur problem ..
    Indranil

  • JTable with Groupable Header

    Hi again, Im have problems with a JTable supporting Groupable Header
    check this code please:
    public class GroupableHeaderExample extends JFrame {
      GroupableHeaderExample() {
        super( "Groupable Header Example" );
        DefaultTableModel dm = new DefaultTableModel();
        dm.setDataVector(new Object[][]{
          {"119","foo","bar","ja","ko","zh"},
          {"911","bar","foo","en","fr","pt"}},
        new Object[]{"SNo.","1","2","Native","2","3"});
        JTable table = new JTable( dm ) {
          protected JTableHeader createDefaultTableHeader() {
         return new GroupableTableHeader(columnModel);
        TableColumnModel cm = table.getColumnModel();
        ColumnGroup g_name = new ColumnGroup("Name");
        g_name.add(cm.getColumn(1));
        g_name.add(cm.getColumn(2));
        ColumnGroup g_lang = new ColumnGroup("Language");
        g_lang.add(cm.getColumn(3));
        ColumnGroup g_other = new ColumnGroup("Others");
        g_other.add(cm.getColumn(4));
        g_other.add(cm.getColumn(5));
        g_lang.add(g_other);
        GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
        header.addColumnGroup(g_name);
        header.addColumnGroup(g_lang);
        JScrollPane scroll = new JScrollPane( table );
        getContentPane().add( scroll );
        setSize( 400, 120 );  
      }it could be like this :
    * |-----------------------------------------------------|
    * |        |       Name      |         Language         |
    * |        |-----------------|--------------------------|
    * |  SNo.  |        |        |        |      Others     |
    * |        |   1    |    2   | Native |-----------------|
    * |        |        |        |        |   2    |   3    | 
    * |-----------------------------------------------------|
    * |        |        |        |        |        |        |
    */but it is looking like this:
    * |-----------------------------------------------------|
    * |  SNo.  |   1    |    2   | Native |   2    |   3    | 
    * |-----------------------------------------------------|
    * |        |        |        |        |        |        |
    */its look like correct, but i think the problem is in one of the clases called. what do you think? ... thanks
    Message was edited by:
    iTzAngel
    Message was edited by:
    iTzAngel

    STOP SPAMMING THE FORUMS!
    http://forum.java.sun.com/thread.jspa?threadID=5202466
    http://forum.java.sun.com/thread.jspa?threadID=5202411
    http://forum.java.sun.com/thread.jspa?threadID=5202439
    http://forum.java.sun.com/thread.jspa?threadID=5202369
    by the way, you are really spamming the forums

  • 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();

  • 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;
    }

  • JTable with row header plus value extraction from headers

    Hi, I am trying to do the following:
    Short Version-
    1. Create a table that has both row and column headers
    2. Allow the user to mouse over any of these headers such that doing so will display an image I have produced on a panel. (I already know how to create the image and how to display it, I'm just not sure how to associate it with a particular row or column header)
    3. Make the row headers look as much as possible like the column headers.
    Slightly Longer Version-
    Column headers will be labled A-H (maximum) while row headers will be labled 1-12 (maximum). Either can be less, however, depending on user input. After the table has been realized, the user will move the mouse over say, header 'H' and when they do, a JPEG image will appear on another panel and a tooltip will appear above the cell showing a formula. This happens when either row or column headers are moused over.
    Currently, I am using the following code from the O'reilly Swing book as a baseline for experimentation but any help you can offer will be appreciated. I'm fairly new to the JTable world... :-(
    TableModel tm = new AbstractTableModel(){
                   String data[] = {"", "a", "b", "c", "d", "e"};
                   String headers [] = {"Row #", "Column1", "Column2", "Column3", "Column4", "Column5"};
                   public int getColumnCount(){ return data.length;}
                   public int getRowCount() { return 1000;}
                   public String getColumnName(int col){ return headers[col];}
                   public Object getValueAt(int row, int col){
                        return data[col] + row;
              //creates a column model for the main table. This model ignores the first
              //column added and sets a minimum width of 150 pixels for all others
              TableColumnModel cm = new DefaultTableColumnModel(){
                   boolean first = true;
                   public void addColumn(TableColumn tc){
                        if(first) {first = false; return;}
                        tc.setMinWidth(150);
                        super.addColumn(tc);
              //Creates a column model that will serve as the row header table. This model
              //picks a maxium width and stores only the first column
              TableColumnModel rowHeaderModel = new DefaultTableColumnModel(){
                   boolean first = true;
                   public void addColumn(TableColumn tc){
                        if(first) {
                             tc.setMaxWidth(tc.getPreferredWidth());
                             super.addColumn(tc);
                             first = false;
              JTable grid = new JTable(tm, cm);
              //set up the header column and hook it up to everything
              JTable headerColumn = new JTable(tm, rowHeaderModel);
              grid.createDefaultColumnsFromModel();
              headerColumn.createDefaultColumnsFromModel();
              //make sure the selection between the main table and the header stay in sync
              grid.setSelectionModel(headerColumn.getSelectionModel());
              headerColumn.setBorder(BorderFactory.createEtchedBorder());
              headerColumn.setBackground(Color.lightGray);
              headerColumn.setColumnSelectionAllowed(false);
              headerColumn.setCellSelectionEnabled(false);
              JViewport jv = new JViewport();
              jv.setView(headerColumn);
              jv.setPreferredSize(headerColumn.getMaximumSize());
              //to make the table scroll properly
              grid.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
              //have to manually attach row headers but after that, the scroll pane
              //keeps them in sync
              JScrollPane jsp = new JScrollPane(grid);
              jsp.setRowHeader(jv);
              jsp.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER, headerColumn.getTableHeader());
              gridPanel.add(jsp, BorderLayout.NORTH);

    There a number of nice examples on JTable: http://www.senun.com/Left/Programming/Java_old/Examples_swing/SwingExamples.html
    Hope you could find something suitable ...
    Regards,
    Anton.

  • ALV Display dynamic column with multiline header

    Hi All.
    I need to create alv display with dynamic number of columns. Also, it contains two header line. Kindly help me in coding.
    The required format is this format.
    Product | Week1 | Week2 |.......| WeekN
    |--||---|--
                | Sales   | Sales   |.......| Sales
    |--| |---|--
    PRD1   | value    | Value    |.......| Value
    PRD2   | value    | Value    |.......| Value
    PRD3   | value    | Value    |.......| Value
    Thanks.
    Sadhna

    Hi Sadhana,
    You mean to say that your internal Table contains
    ABCDEF are the fields in your Internal table.
    A--BCD---E-----F
    1--12---13---a11----1
    2--11---01---b9-----0
    3--01---00---c32----0
    4--14---01---d21----0
    Now using Dynamic Internal Table it should display the output as follow :
    A--BCF---a---b-c----d
    1--12---13---111-9-32--21
    Here you want to display the the fields of D as header and E as its corresponding values...?
    Please let me knwo if you mean the same..
    Regards,
    Kittu

  • 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