title: How to print preview a JTable
body: <p>I'm a junior Java developer and I want to build a class that takes a JTable and previews on screen how it will be printed on the default printer. This is what we use to call as "Print Preview", just like MS Word, Excel, etc.</p>
  
  <p>As we already know Java does not support this functionality out-of-the-box.</p>
  
  <p>Based on some examples I've found googling I built two classes. The first one TestPreview.java justs shows the JTable and the second one PrintPreview.java previews how the JTable will be printed on the printer.</p>
  
  <p>I have two buttons to go through the pages, "PREV" and "NEXT" and "Print' button to print the JTable. 
  My problem is that when my JTable has too many rows and spans in more than one page PrintPreview does not work. It shows the same page again and again. Also, it does not show the entire JTable data, but only some of them and I can't figure out why.</p>
  
  <p>Please help.</p>
  
  <p>Below is my two classes</p>
  
  <p><em><strong>TestPreview.java</em></strong></p>
  
  <pre><code>package printpreviewdemo;
  
  import javax.swing.*;
  import java.awt.BorderLayout;
  import java.awt.FlowLayout;
  import java.awt.Frame;
  import java.awt.event.*;
  import java.awt.print.*;
  import java.text.MessageFormat;
  import javax.print.attribute.*;
  import javax.print.attribute.standard.MediaPrintableArea;
  import javax.print.attribute.standard.OrientationRequested;
  import javax.print.attribute.standard.Sides;
  import javax.swing.JTable.PrintMode;
  
  class TestPreview extends JFrame implements ActionListener {
      PrinterJob printerJob = PrinterJob.getPrinterJob();
      HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
      JTable table = null;
  
      public TestPreview() {
          super("Test of Print Preview");
          getContentPane().add(createTable());
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
          setExtendedState(Frame.MAXIMIZED_BOTH);
          setVisible(true);
      }
  
      private JPanel createTable() {
         String val[][] = {
              {"A", "Test 01", "A", "Test 01"}, 
              {"B", "Test 02", "B", "Test 02"}, 
              {"C", "Test 03", "C", "Test 03"},
              {"D", "Test 04", "D", "Test 04"}, 
              {"E", "Test 05", "E", "Test 05"}, 
              {"F", "Test 06", "F", "Test 06"},
              {"G", "Test 01", "G", "Test 01"}, 
              {"H", "Test 02", "H", "Test 02"}, 
              {"I", "Test 03", "I", "Test 03"},
              {"J", "Test 03", "J", "Test 03"},
              {"K", "Test 04", "K", "Test 04"}, 
              {"L", "Test 05", "L", "Test 05"}, 
              {"M", "Test 06", "M", "Test 06"},
              {"N", "Test 01", "N", "Test 01"}, 
              {"O", "Test 02", "O", "Test 02"}, 
              {"P", "Test 03", "P", "Test 03"},
              {"Q", "Test 04", "Q", "Test 04"}, 
              {"R", "Test 05", "R", "Test 05"}, 
              {"S", "Test 06", "S", "Test 06"},
              {"T", "Test 01", "T", "Test 01"}, 
              {"U", "Test 02", "U", "Test 02"}, 
              {"V", "Test 03", "V", "Test 03"},
              {"W", "Test 04", "W", "Test 04"}, 
              {"X", "Test 05", "X", "Test 05"}, 
              {"Y", "Test 06", "Y", "Test 06"},
              {"Z", "Test 01", "Z", "Test 01"},
              {"1", "Test 02", "1", "Test 02"}, 
              {"2", "Test 03", "2", "Test 03"},
              {"3", "Test 04", "3", "Test 04"}, 
              {"4", "Test 05", "4", "Test 05"}, 
              {"5", "Test 06", "5", "Test 06"},
              {"6", "Test 01", "6", "Test 01"}, 
              {"7", "Test 02", "7", "Test 02"}, 
              {"8", "Test 03", "8", "Test 03"},
              {"9", "Test 04", "9", "Test 04"}, 
              {"10", "Test 05","10", "Test 05"},
              {"11", "Test 02","11", "Test 02"}, 
              {"12", "Test 03","12", "Test 03"},
              {"13", "Test 04","13", "Test 04"}, 
              {"14", "Test 05","14", "Test 05"}, 
              {"15", "Test 06","15", "Test 06"},
              {"16", "Test 01","16", "Test 01"}, 
              {"17", "Test 02","17", "Test 02"}, 
              {"18", "Test 03","18", "Test 03"},
              {"19", "Test 04","19", "Test 04"}, 
              {"20", "Test 05","20", "Test 05"},
              {"30", "Test 05","30", "Test 05"},
              {"31", "Test 02","31", "Test 02"}, 
              {"32", "Test 03","32", "Test 03"},
              {"33", "Test 04","33", "Test 04"}, 
              {"34", "Test 05","34", "Test 05"}, 
              {"35", "Test 06","35", "Test 06"},
              {"36", "Test 01","36", "Test 01"}, 
              {"37", "Test 02","37", "Test 02"}, 
              {"38", "Test 03","38", "Test 03"},
              {"39", "Test 04","39", "Test 04"}, 
              {"40", "Test 05","40", "Test 05"},
              {"40", "Test 05","40", "Test 05"},
              {"41", "Test 02","41", "Test 02"}, 
              {"42", "Test 03","42", "Test 03"},
              {"43", "Test 04","43", "Test 04"}, 
              {"44", "Test 05","44", "Test 05"}, 
              {"45", "Test 06","45", "Test 06"},
              {"46", "Test 01","46", "Test 01"}, 
              {"47", "Test 02","47", "Test 02"}, 
              {"48", "Test 03","48", "Test 03"},
              {"49", "Test 04","49", "Test 04"}, 
              {"50", "Test 05","50", "Test 05"},
              {"50", "Test 05","50", "Test 05"},
              {"51", "Test 02","51", "Test 02"}, 
              {"52", "Test 03","52", "Test 03"},
              {"53", "Test 04","53", "Test 04"}, 
              {"54", "Test 05","54", "Test 05"}, 
              {"55", "Test 06","55", "Test 06"},
              {"56", "Test 01","56", "Test 01"}, 
              {"57", "Test 02","57", "Test 02"}, 
              {"58", "Test 03","58", "Test 03"},
              {"59", "Test 04","59", "Test 04"}, 
              {"60", "Test 05","60", "Test 05"}
          };
  
          String headers[] = {"A", "B", "C", "D"};
          table = new JTable(val, headers);
          JButton previewButton = new JButton("Preview Table");
          previewButton.addActionListener(this);
          JPanel panel = new JPanel(new BorderLayout()), top = new JPanel(new FlowLayout());
          top.add(previewButton);
          panel.add(top, "North"); 
          panel.add(new JScrollPane(table), "Center");
          return panel;
      }
  
      @Override
      public void actionPerformed(ActionEvent ae) {
          if (ae.getActionCommand().equals("Preview Table"))
              attributes.add(new MediaPrintableArea(6, 6, 198, 278, MediaPrintableArea.MM)); // A4: 210x297mm
              attributes.add(Sides.DUPLEX);
              attributes.add(OrientationRequested.LANDSCAPE);
              new PrintPreview(
                  table.getPrintable(PrintMode.FIT_WIDTH, null, new MessageFormat("Page {0}") ), 
                  printerJob.getPageFormat(attributes)
              );
      }
  
      public static void main(String arg[]) {
          new TestPreview();
      }
  }
  </code></pre>
  
  <p><em><strong>PrintPreview.java</em></strong></p>
  
  <pre><code>package printpreviewdemo;
  
  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.*;
  import java.awt.image.BufferedImage;
  import java.awt.print.*;
  
  class PrintPreview extends JFrame implements ActionListener, ItemListener {
      JButton printButton = new JButton("Print");
      Pageable pageable = null;
      double scale = 1.0;
      Page page[] = null;
      JComboBox combobox = new JComboBox();
      CardLayout cardlayout = new CardLayout();
      JPanel previewPanel = new JPanel(cardlayout);
      JButton backButton = new JButton("PREV"), forwardButton = new JButton("NEXT");
  
      public PrintPreview(final Printable printable, final PageFormat pageFormat) {
          super("Print Preview");        
          pageable = new Pageable() {
              @Override
              public int getNumberOfPages() {
                  Graphics graphics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics();                
                  int numPages = 0;
                  try {
                      while (printable.print(graphics, pageFormat, numPages) == Printable.PAGE_EXISTS) {
                          numPages++;
                      }
                  } catch (Exception ex) {
                  }
                  return numPages;
              }
  
              @Override
              public PageFormat getPageFormat(int x) {
                  return pageFormat;
              }
  
              @Override
              public Printable getPrintable(int x) {
                  return printable;
              }
          };
          createPreview();
      }
  
      private void createPreview() {
          page = new Page[pageable.getNumberOfPages()];
          PageFormat pageFormat = pageable.getPageFormat(0);
          Dimension size = new Dimension((int) pageFormat.getPaper().getWidth(), (int) pageFormat.getPaper().getHeight());
          if (pageFormat.getOrientation() != PageFormat.PORTRAIT) {
              size = new Dimension(size.height, size.width);
          }
          for (int i = 0; i &lt; page.length; i++) {
              combobox.addItem("" + (i + 1));
              page[i] = new Page(i, size);
              previewPanel.add("" + (i + 1), new JScrollPane(page[i]));
          }
          setTopPanel();
          getContentPane().add(previewPanel, "Center");
          pack();
          setExtendedState(Frame.MAXIMIZED_BOTH);
          setVisible(true);
      }
  
      private void setTopPanel() {
          FlowLayout fl = new FlowLayout();
          GridBagLayout gbl = new GridBagLayout();
  
          JPanel topPanel = new JPanel(gbl), temp = new JPanel(fl);
          backButton.addActionListener(this);
          forwardButton.addActionListener(this);
          backButton.setEnabled(false);
          forwardButton.setEnabled(page.length &gt; 1);
  
          temp.add(combobox);
          temp.add(backButton);
          temp.add(forwardButton);
          temp.add(printButton);
  
          topPanel.add(temp);
          printButton.addActionListener(this);
          combobox.addItemListener(this);
          getContentPane().add(topPanel, "North");
      }
  
      @Override
      public void itemStateChanged(ItemEvent ie) {
          cardlayout.show(previewPanel, (String) combobox.getSelectedItem());
          backButton.setEnabled(combobox.getSelectedIndex() == 0 ? false : true);
          forwardButton.setEnabled(combobox.getSelectedIndex() == combobox.getItemCount() - 1 ? false : true);
          validate();
      }
  
      @Override
      public void actionPerformed(ActionEvent ae) {
          Object o = ae.getSource();
          if (o == printButton) {
              try {
                  PrinterJob pj = PrinterJob.getPrinterJob();
                  pj.defaultPage(pageable.getPageFormat(0));
                  pj.setPageable(pageable);
                  if (pj.printDialog()) {
                      pj.print();
                  }
              } catch (Exception ex) {
                  JOptionPane.showMessageDialog(null, ex.toString(), "Error in Printing", 1);
              }
          } else if (o == backButton) {
              combobox.setSelectedIndex(combobox.getSelectedIndex() == 0 ? 0 : combobox.getSelectedIndex() - 1);
              if (combobox.getSelectedIndex() == 0) {
                  backButton.setEnabled(false);
              }
          } else if (o == forwardButton) {
              combobox.setSelectedIndex(combobox.getSelectedIndex() == combobox.getItemCount() - 1 ? 0 : combobox.getSelectedIndex() + 1);
              if (combobox.getSelectedIndex() == combobox.getItemCount() - 1) {
                  forwardButton.setEnabled(false);
              }
          }
      }
  
      class Page extends JLabel {
          final int n;
          final PageFormat pageformat;
          BufferedImage bufferimage = null;
          Dimension size = null;
  
          public Page(int currentpage, Dimension size) {
              this.size = size;
              bufferimage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
              n = currentpage;
              pageformat = pageable.getPageFormat(n);
              Graphics g = bufferimage.getGraphics();
              g.setColor(Color.WHITE);                       
              g.fillRect(0, 0, (int) pageformat.getWidth(), (int) pageformat.getHeight());
              try {
                  pageable.getPrintable(n).print(g, pageformat, n);
              } catch (Exception ex) {
              }
              setIcon(new ImageIcon(bufferimage));
          }
      }
  }
  </code></pre>