2010-05-19 19 views
1

J'essaye de faire un composant imprimable (un document de facture). J'utilise JComponent au lieu de JPanel parce que je ne veux pas d'arrière-plan. Le composant a de nombreux sous-composants.Toutes les parties de mon composant Printable Swing n'impriment pas

Le composant principal implémente Printable et possède une méthode print qui appelle printAll(g) de sorte que tous les sous-composants doivent être imprimés. Mais mes sous-composants ne s'impriment pas.

Qu'est-ce qui me manque? Tous les sous-composants doivent également implémenter Printable?

Dans mon code ci-dessous, le TopHeader n'est pas imprimé.

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.print.PageFormat; 
import java.awt.print.Printable; 
import java.awt.print.PrinterException; 
import java.awt.print.PrinterJob; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

public class PPanel extends JComponent implements Printable { 
    static double w; 
    static double h; 

    public PPanel() { 
     this.setLayout(new BorderLayout()); 

     this.add(new JLabel("Document Body"), BorderLayout.CENTER); 
     this.add(new TopHeader(), BorderLayout.NORTH); 
    } 

    class TopHeader extends JComponent { 
     public TopHeader() { 
      this.setLayout(new BorderLayout()); 
      JLabel companyName = new JLabel("Company name"); 
      JLabel docType = new JLabel("Document type"); 
      this.add(companyName, BorderLayout.WEST); 
      this.add(docType, BorderLayout.EAST); 
     } 
    } 

    public static void main(String[] args) { 
     final PPanel p = new PPanel(); 
     PrinterJob job = PrinterJob.getPrinterJob(); 
     job.setPrintable(p); 
     try { 
      job.print(); 
     } catch (PrinterException ex) { 
      // print failed 
     } 
      // Preview 
     new JFrame() {{ getContentPane().add(p); this.setSize((int)w, (int)h); setVisible(true); }}; 

    } 

    @Override 
    public int print(Graphics g, PageFormat pf, int page) 
      throws PrinterException { 
     if (page > 0) { 
      return NO_SUCH_PAGE; 
     } 

     Graphics2D g2d = (Graphics2D)g; 
     g2d.translate(pf.getImageableX(), pf.getImageableY()); 

     w = pf.getImageableWidth(); 
     h = pf.getHeight(); 

     this.setSize((int)w, (int)h); 
     this.setPreferredSize(new Dimension((int)w, (int)h)); 
     this.doLayout(); 

     this.printAll(g); 
     return PAGE_EXISTS; 
    } 
} 

Répondre

1

Vous pourriez probablement boucle à travers le Component[] retourné par getComponents(), mais un expédient simple est illustré ci-dessous. Notez la différence entre l'aperçu de l'écran et l'impression. Notez également l'utilisation de validate() au lieu de doLayout(). Enfin, pour faciliter la prévisualisation, cet exemple implémente Using Print Setup Dialogs.

Addendum: Vous pouvez également regarder Printing Support in Swing Components et de comparer l'approche adoptée dans ce example.

import java.awt.*; 
import java.awt.print.*; 
import javax.swing.*; 

public class PPanel extends JComponent implements Printable { 

    private JComponent top = new TopHeader(); 
    private JComponent mid = new JLabel("Document Body"); 

    public PPanel() { 
     this.setLayout(new BorderLayout()); 
     this.add(top, BorderLayout.NORTH); 
     this.add(mid, BorderLayout.CENTER); 
    } 

    private static class TopHeader extends JComponent { 

     public TopHeader() { 
      this.setLayout(new BorderLayout()); 
      JLabel companyName = new JLabel("Company name"); 
      JLabel docType = new JLabel("Document type"); 
      this.add(companyName, BorderLayout.WEST); 
      this.add(docType, BorderLayout.EAST); 
     } 
    } 

    @Override 
    public int print(Graphics g, PageFormat pf, int page) 
     throws PrinterException { 
     if (page > 0) { 
      return NO_SUCH_PAGE; 
     } 
     Graphics2D g2d = (Graphics2D)g; 
     g2d.translate(pf.getImageableX(), pf.getImageableY()); 
     int w = (int)pf.getImageableWidth(); 
     int h = (int)pf.getImageableHeight(); 
     top.setSize(new Dimension(w, top.getPreferredSize().height)); 
     this.setSize(w, h); 
     this.validate(); 
     this.printAll(g2d); 
     return PAGE_EXISTS; 
    } 

    public static void main(String[] args) { 
     final PPanel p = new PPanel(); 
     // Preview before print() 
     new JFrame() { 
      { 
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       this.add(p); 
       this.pack(); 
       this.setVisible(true); 
      } 
     }; 
     PrinterJob pj = PrinterJob.getPrinterJob(); 
     PageFormat pf = pj.pageDialog(pj.defaultPage()); 
     pj.setPrintable(p, pf); 
     if (pj.printDialog()) { 
      try { 
       pj.print(); 
      } catch (PrinterException pe) { 
       pe.printStackTrace(); 
      } 
     } 
    } 
} 
+0

Merci, mais je ne comprends pas comment je peux utiliser I.e. 'javax.swing.text.JTextComponent.print()' dans mon exemple si j'utilise un JTextField de mon JLabel. La méthode 'print()' n'est-elle pas appelée quand je fais 'printAll (g)'? Ou dois-je écrire un code spécifique pour cela? – Jonas

+0

Cela dépend si vous voulez imprimer ce qui est sur l'écran ou ce qui est dans le 'JTextComponent' qui peut être trop grand pour s'adapter sans défilement. – trashgod