views:

348

answers:

3

I am printing a Swing component that contains text. The Swing component renders the text just fine on the screen, but, when I print it (to a .tif file), the characters are all smashed together. Why is this?

Run this code to see what I mean:

import javax.swing.*;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

public final class PrintingDemo2 implements Printable {

    private final JTextPane textPane;
    private static final String WORDS = "GOOD MORNING\u00AE AMERICA";
    private static final String TEXT = WORDS + '\n' + WORDS + '\n' + WORDS + '\n' + WORDS + '\n' + WORDS + '\n' + WORDS;

    public static void main(String[] args) {
        new PrintingDemo2();
    }

    public PrintingDemo2() {
        textPane = new JTextPane();
        textPane.setText(TEXT);
        final StyledDocument document = textPane.getStyledDocument();

        String[] fontFamilies = new String[]{"Tahoma", "SimSum", "MS Mincho", "Batang", "Arial", "Times New Roman"};
        for (int i = 0; i < fontFamilies.length; i++) {
            final MutableAttributeSet attributeSet = new SimpleAttributeSet();
            StyleConstants.setFontFamily(attributeSet, fontFamilies[i]);
            StyleConstants.setFontSize(attributeSet, 14);
            document.setParagraphAttributes(i * 22, 21, attributeSet, true);
        }

        final AbstractButton printContextButton = new JButton("Print Context");
        printContextButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                final PrinterJob job = PrinterJob.getPrinterJob();
                job.setPrintable(PrintingDemo2.this);
                try {
                    job.print();
                } catch (PrinterException ex) {
                    throw new RuntimeException("Printing Failed.", ex);
                }
            }
        });

        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
        contentPane.add(printContextButton);
        contentPane.add(new JScrollPane(textPane));
        frame.setSize(400, 200);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.setVisible(true);
            }
        });
    }

    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        if (pageIndex >= 1) return Printable.NO_SUCH_PAGE;

        RepaintManager mgr = RepaintManager.currentManager(textPane);
        mgr.setDoubleBufferingEnabled(false);
        final Graphics2D graphics2D = (Graphics2D) graphics;
        graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
        textPane.paint(graphics);
        mgr.setDoubleBufferingEnabled(true);

        return Printable.PAGE_EXISTS;
    }
}
A: 

Check that the printed font is the same one you're seeing in the screen form. If the printer is substituting a font, it probably kerns and hints differently than the screen font.

To start with, try trimming it down to only one font. There's a lot of moving parts there.

Update

Okay, I just tried it, and it seems to work fine, printing to a LaserJet 1300 from Mac OS/X 10.5.6.

I'd try a different printing device; I'm betting that it's happening after Java s done with the data.

Charlie Martin
I'm actually printing it to a .tif file, not to a real printer. Did you try running the code?
Paul Reiners
I just did, and the output on my physical printer looks just fine.
Charlie Martin
+3  A: 

You could try rasterizing it (painting it to a BufferedImage at 300dpi) and then printing that image. Hacky, and bad for performance (huge rasterized file sent to printer instead of vector data), but at least you won't have font problems.

To rasterize it, create a BufferedImage that is 4.17x (300/72) the size of your on-screen panel and scale its graphics object be the same abount, and then paint the panel onto the buffered image's Graphics2D object.

Disclaimer: this isn't elegant and I know it. If someone knows how to convince every make and model of printer to receive fonts from a Java printing process, please chime in!

CarlG
A: 

i want to know how to print a text

arunkumar