*
o PrintExample.java Demonstrates printing a Graphics2D object.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.print.*;
/** An example of a printable window in Java 1.2. The key point
* here is that any component is printable in Java 1.2.
* However, you have to be careful to turn off double buffering
* globally (not just for the top-level window).
* See the PrintUtilities class for the printComponent method
* that lets you print an arbitrary component with a single
* function call.
*
*/
public class PrintExample extends JFrame
implements ActionListener {
public static void main(String[] args) {
new PrintExample();
}
public PrintExample() {
super("Printing Swing Components in JDK 1.2");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
JButton printButton = new JButton("Print");
printButton.addActionListener(this);
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(Color.white);
buttonPanel.add(printButton);
content.add(buttonPanel, BorderLayout.SOUTH);
DrawingPanel drawingPanel = new DrawingPanel();
content.add(drawingPanel, BorderLayout.CENTER);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
PrintUtilities.printComponent(this);
}
}
Uses the following classes:
+ PrintUtilities.java Simple utility class to support printing graphical windows in JDK 1.2.
import java.awt.*;
import javax.swing.*;
import java.awt.print.*;
/** A simple utility class that lets you very simply print
* an arbitrary component in JDK 1.2. Just pass the
* component to PrintUtilities.printComponent. The
* component you want to print doesn't need a print method
* and doesn't have to implement any interface or do
* anything special at all.
*
* If you are going to be printing many times, it is marginally
* more efficient to first do the following:
*
* PrintUtilities printHelper =
* new PrintUtilities(theComponent);
*
* then later do printHelper.print(). But this is a very tiny
* difference, so in most cases just do the simpler
* PrintUtilities.printComponent(componentToBePrinted).
*
*/
public class PrintUtilities implements Printable {
protected Component componentToBePrinted;
public static void printComponent(Component c) {
new PrintUtilities(c).print();
}
public PrintUtilities(Component componentToBePrinted) {
this.componentToBePrinted = componentToBePrinted;
}
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(this);
if (printJob.printDialog())
try {
printJob.print();
} catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
// General print routine for JDK 1.2. Use PrintUtilities2
// for printing in JDK 1.3.
public int print(Graphics g, PageFormat pageFormat,
int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
/** The speed and quality of printing suffers dramatically if
* any of the containers have double buffering turned on,
* so this turns it off globally. This step is only
* required in JDK 1.2.
*/
public static void disableDoubleBuffering(Component c) {
RepaintManager currentManager =
RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(false);
}
/** Reenables double buffering globally. This step is only
* required in JDK 1.2.
*/
public static void enableDoubleBuffering(Component c) {
RepaintManager currentManager =
RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(true);
}
}
//
+ DrawingPanel.java A basic JPanel containing a Java 2D drawing.
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
/** A window with a custom paintComponent method.
* Illustrates that you can make a general-purpose method
* that can print any component, regardless of whether
* that component performs custom drawing.
* See the PrintUtilities class for the printComponent method
* that lets you print an arbitrary component with a single
* function call.
*
*/
public class DrawingPanel extends JPanel {
private int fontSize = 90;
private String message = "Java 2D";
private int messageWidth;
public DrawingPanel() {
setBackground(Color.white);
Font font = new Font("Serif", Font.PLAIN, fontSize);
setFont(font);
FontMetrics metrics = getFontMetrics(font);
messageWidth = metrics.stringWidth(message);
int width = messageWidth*5/3;
int height = fontSize*3;
setPreferredSize(new Dimension(width, height));
}
/** Draws a black string with a tall angled "shadow"
* of the string behind it.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
int x = messageWidth/10;
int y = fontSize*5/2;
g2d.translate(x, y);
g2d.setPaint(Color.lightGray);
AffineTransform origTransform = g2d.getTransform();
g2d.shear(-0.95, 0);
g2d.scale(1, 3);
g2d.drawString(message, 0, 0);
g2d.setTransform(origTransform);
g2d.setPaint(Color.black);
g2d.drawString(message, 0, 0);
}
}
o PrintUtilities2.java Simple utility class to support printing graphical windows in JDK 1.3 and later. Inherits from PrintUtilities.java.
import java.awt.*;
import javax.swing.*;
import java.awt.print.*;
/** A simple utility class for printing an arbitrary
* component in JDK 1.3. The class relies on the
* fact that in JDK 1.3 the JComponent class overrides
* print (in Container) to automatically set a flag
* that disables double buffering before the component
* is painted. If the printing flag is set, paint calls
* printComponent, printBorder, and printChildren.
*
* To print a component, just pass the component to
* PrintUtilities2.printComponent(componentToBePrinted).
*
*/
public class PrintUtilities2 extends PrintUtilities {
public static void printComponent(Component c) {
new PrintUtilities2(c).print();
}
public PrintUtilities2(Component componentToBePrinted) {
super(componentToBePrinted);
}
// General print routine for JDK 1.3. Use PrintUtilities1
// for printing in JDK 1.2.
public int print(Graphics g, PageFormat pageFormat,
int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
componentToBePrinted.print(g2d);
return(PAGE_EXISTS);
}
}
}
* FileTransfer.java Demonstrates the proper technique for updating Swing components in a multithreaded program.
/**
// Final version of FileTransfer. Modification of the
// label is thread safe.
public class FileTransfer extends Thread {
private String filename;
private JLabel label;
public FileTransfer(String filename, JLabel label) {
this.filename = filename;
this.label = label;
}
public void run() {
try {
// Place the runnable object to update the label
// on the event queue. The invokeAndWait method
// will block until the label is updated.
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
label.setText("Transferring " + filename);
}
});
} catch(InvocationTargetException ite) {
} catch(InterruptedException ie) { }
// Transfer file to server. Lengthy process.
doTransfer(...);
// Perform the final update to the label from
// within the runnable object. Use invokeLater;
// blocking is not necessary.
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
label.setText("Transfer completed");
}
});
}
}
* WindowUtilities.java Utility class that simplifies creating a window and setting the look and feel.
* ExitListener.java A WindowListener with support to close the window.