The Clipboard


One of the most useful and convenient user interface mechanisms of graphical user interface environments (such as Windows and the X Window System) is cut and paste. You select some data in one program and cut or copy them to the clipboard. Then, you select another program and paste the clipboard contents into that application. Using the clipboard, you can transfer text, images, or other data from one document to another, or, of course, from one place in a document to another place in the same document. Cut and paste is so natural that most computer users never think about it.

However, JDK 1.0 did not support cut and paste. JDK 1.1 implemented a rudimentary clipboard mechanism. That mechanism has been gradually improved and is now quite usable on a number of platforms.

Even though the clipboard is conceptually simple, implementing clipboard services is actually harder than you might think. Suppose you copy text from a word processor to the clipboard. If you paste that text into another word processor, then you expect that the fonts and formatting will stay intact. That is, the text in the clipboard needs to retain the formatting information. But if you paste the text into a plain text field, then you expect that just the characters are pasted in, without additional formatting codes. To support this flexibility, the data provider can offer the clipboard data in multiple formats, and the data consumer can pick one of them.

The system clipboard implementations of Microsoft Windows and the Macintosh are similar, but, of course, there are slight differences. However, the X Window System clipboard mechanism is much more limitedcutting and pasting of anything but plain text is only sporadically supported. You should consider these limitations when trying out the programs in this section.

NOTE

Check out the file jre/lib/flavormap.properties on your platform to get an idea about what kinds of objects can be transferred between Java programs and the system clipboard.


Often, programs need to support cut and paste of data types that the system clipboard cannot handle. The data transfer API supports the transfer of arbitrary local object references in the same virtual machine. Between different virtual machines, you can transfer serialized objects and references to remote objects.

Table 7-5 summarizes the data transfer capabilities of the clipboard mechanism.

Table 7-5. Capabilities of the Java Data Transfer Mechanism

Transfer

Format

Between a Java program and a native program

Text, images, file lists, . . . (depending on the host platform)

Between two cooperating Java programs

Serialized and remote objects

Within one Java program

Any object


Classes and Interfaces for Data Transfer

Data transfer in the Java technology is implemented in a package called java.awt.datatransfer. Here is an overview of the most important classes and interfaces of that package.

  • Objects that can be transferred via a clipboard must implement the TRansferable interface.

  • The Clipboard class describes a clipboard. Transferable objects are the only items that can be put on or taken off a clipboard. The system clipboard is a concrete example of a Clipboard.

  • The DataFlavor class describes data flavors that can be placed on the clipboard.

  • The StringSelection class is a concrete class that implements the transferable interface. It transfers text strings.

  • A class must implement the ClipboardOwner interface if it wants to be notified when the clipboard contents have been overwritten by someone else. Clipboard ownership enables "delayed formatting" of complex data. If a program transfers simple data (such as a string), then it simply sets the clipboard contents and moves on to do the next thing. However, if a program will place complex data that can be formatted in multiple flavors onto the clipboard, then it may not actually want to prepare all the flavors, since there is a good chance that most of them are never needed. However, then it needs to hang on to the clipboard data so that it can create the flavors later when they are requested. The clipboard owner is notified (by a call to its lostOwnership method) when the contents of the clipboard change. That tells it that the information is no longer needed. In our sample programs, we don't worry about clipboard ownership.

Transferring Text

The best way to get comfortable with the data transfer classes is to start with the simplest situation: transferring text to and from the system clipboard. The idea of the following program is simple. First, get a reference to the system clipboard.

 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 

For strings to be transferred to the clipboard, they must be wrapped into StringSelection objects. The constructor takes the text you want to transfer.

 String text = . . . StringSelection selection = new StringSelection(text); 

The actual transfer is done by a call to setContents, which takes a StringSelection object and a ClipBoardOwner as parameters. If you are not interested in designating a clipboard owner, set the second parameter to null.

 clipboard.setContents(selection, null); 

Starting with JDK 5.0, you can bypass the transferable and query the clipboard directly.

Let us look at the reverse operation, reading a string from the clipboard. Starting with JDK 5.0, this is quite simple:

 DataFlavor flavor = DataFlavor.stringFlavor; if (clipboard.isDataFlavorAvailable(flavor)    String text = (String) clipboard.getData(flavor); 

Before JDK 5.0, you had to retrieve the transferable and query it for the available flavors:

 Transferable contents = clipBoard.getContents(null); if (contents != null && contents.isDataFlavorSupported(flavor))    String text = (String) contents.getTransferData(flavor); 

According to the API documentation, the parameter of the getContents call is an Object reference of the requesting object. It is not clear why the clipboard collects this information.

The return value of getContents may be null. That indicates that the clipboard is either empty or that it has no data that the Java platform knows how to retrieve.

Example 7-16 is a program that demonstrates cutting and pasting between a Java application and the system clipboard. Figure 7-45 shows a screen shot. If you select an area of text in the text area and click Copy, then the selected text is copied to the system clipboard. As Figure 7-46 shows, the copied text is indeed stored on the system clipboard. (Run the program c:\windows\system32\clipbrd to display the clipboard viewer in Windows.) When you subsequently click the Paste button, the contents of the clipboard (which may come from a native program) are pasted at the cursor position.

Example 7-16. TextTransferTest.java
   1. import java.awt.*;   2. import java.awt.datatransfer.*;   3. import java.awt.event.*;   4. import java.io.*;   5. import javax.swing.*;   6.   7. /**   8.    This program demonstrates the transfer of text   9.    between a Java application and the system clipboard.  10. */  11. public class TextTransferTest  12. {  13.    public static void main(String[] args)  14.    {  15.       JFrame frame = new TextTransferFrame();  16.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  17.       frame.setVisible(true);  18.    }  19. }  20.  21. /**  22.    This frame has a text area and buttons for copying and  23.    pasting text.  24. */  25. class TextTransferFrame extends JFrame  26. {  27.    public TextTransferFrame()  28.    {  29.       setTitle("TextTransferTest");  30.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  31.  32.       textArea = new JTextArea();  33.       add(new JScrollPane(textArea), BorderLayout.CENTER);  34.       JPanel panel = new JPanel();  35.  36.       JButton copyButton = new JButton("Copy");  37.       panel.add(copyButton);  38.       copyButton.addActionListener(new  39.          ActionListener()  40.          {  41.             public void actionPerformed(ActionEvent event)  42.             {  43.                copy();  44.             }  45.          });  46.  47.       JButton pasteButton = new JButton("Paste");  48.       panel.add(pasteButton);  49.       pasteButton.addActionListener(new  50.          ActionListener()  51.          {  52.             public void actionPerformed(ActionEvent event)  53.             {  54.                paste();  55.             }  56.          });  57.  58.       add(panel, BorderLayout.SOUTH);  59.    }  60.  61.    /**  62.       Copies the selected text to the system clipboard.  63.    */  64.    private void copy()  65.    {  66.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  67.       String text = textArea.getSelectedText();  68.       if (text == null) text = textArea.getText();  69.       StringSelection selection = new StringSelection(text);  70.       clipboard.setContents(selection, null);  71.    }  72.  73.    /**  74.       Pastes the text from the system clipboard into the  75.       text area.  76.    */  77.    private void paste()  78.    {  79.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  80.       DataFlavor flavor = DataFlavor.stringFlavor;  81.       if (clipboard.isDataFlavorAvailable(flavor))  82.       {  83.          try  84.          {  85.             String text = (String) clipboard.getData(flavor);  86.             textArea.replaceSelection(text);  87.          }  88.          catch (UnsupportedFlavorException e)  89.          {  90.             JOptionPane.showMessageDialog(this, e);  91.          }  92.          catch (IOException e)  93.          {  94.             JOptionPane.showMessageDialog(this, e);  95.          }  96.       }  97.    }  98.  99.    private JTextArea textArea; 100. 101.    private static final int DEFAULT_WIDTH = 300; 102.    private static final int DEFAULT_HEIGHT = 300; 103. } 

Figure 7-45. The TextTransferTest program


Figure 7-46. The Windows clipboard viewer after a copy



 java.awt.Toolkit 1.0 

  • Clipboard getSystemClipboard() 1.1

    gets the system clipboard.


 java.awt.datatransfer.Clipboard 1.1 

  • TRansferable getContents(Object requester)

    gets the clipboard contents.

    Parameters:

    requester

    The object requesting the clipboard contents; this value is not actually used


  • void setContents(Transferable contents, ClipboardOwner owner)

    puts contents on the clipboard.

    Parameters:

    contents

    The TRansferable encapsulating the contents

     

    owner

    The object to be notified (via its lostOwnership method) when new information is placed on the clipboard, or null if no notification is desired


  • boolean isDataFlavorAvailable(DataFlavor flavor) 5.0

    returns true if the clipboard has data in the given flavor.

  • Object getData(DataFlavor flavor) 5.0

    gets the data in the given flavor, or throws an UnsupportedFlavorException if no data are available in the given flavor.


 java.awt.datatransfer.ClipboardOwner 1.1 

  • void lostOwnership(Clipboard clipboard, Transferable contents)

    notifies this object that it is no longer the owner of the contents of the clipboard.

    Parameters:

    clipboard

    The clipboard onto which the contents were placed

     

    contents

    The item that this owner had placed onto the clipboard



 java.awt.datatransfer.Transferable 1.1 

  • boolean isDataFlavorSupported(DataFlavor flavor)

    returns true if the specified flavor is one of the supported data flavors; false otherwise.

  • Object getTransferData(DataFlavor flavor)

    returns the data, formatted in the requested flavor. Throws an UnsupportedFlavorException if the flavor requested is not supported.

The Transferable Interface and Data Flavors

As of JDK 5.0, you can ask the clipboard to list all available flavors:

 DataFlavor[] flavors = clipboard.getAvailableDataFlavors() 

In older versions of the JDK, you first got the clipboard contentsan object that implements the transferable interfaceand queried it for the available flavors:

 Transferable contents = clipBoard.getContents(null); if (contents != null)    flavors = transferable.getTransferDataFlavors(); 

You can also install a FlavorListener onto the clipboard. The listener is notified when the collection of data flavors on the clipboard changes. See the API notes for details.

A DataFlavor is defined by two characteristics:

  • A MIME type name (such as "image/gif")

  • A representation class for accessing the data (such as java.awt.Image)

In addition, every data flavor has a human-readable name (such as "GIF Image").

The representation class can be specified with a class parameter in the MIME type, for example,

 image/gif;class=java.awt.Image 

NOTE

This is just an example to show the syntax. There is no standard data flavor for transferring GIF image data.


If no class parameter is given, then the representation class is InputStream.

For transferring local, serialized, and remote Java objects, Sun Microsystems defines three MIME types:

 application/x-java-jvm-local-objectref application/x-java-serialized-object application/x-java-remote-object 

NOTE

The x- prefix indicates that this is an experimental name, not one that is sanctioned by IANA, the organization that assigns standard MIME type names.


For example, the standard stringFlavor data flavor is described by the MIME type

 application/x-java-serialized-object;class=java.lang.String 


 java.awt.datatransfer.DataFlavor 1.1 

  • DataFlavor(String mimeType, String humanPresentableName)

    creates a data flavor that describes stream data in a format described by a MIME type.

    Parameters:

    mimeType

    A MIME type string

     

    humanPresentableName

    A more readable version of the name


  • DataFlavor(Class class, String humanPresentableName)

    creates a data flavor that describes a Java platform class. Its MIME type is application/x-java-serialized-object;class=className.

    Parameters:

    class

    The class that is retrieved from the TRansferable

     

    humanPresentableName

    A readable version of the name


  • String getMimeType()

    returns the MIME type string for this data flavor.

  • boolean isMimeTypeEqual(String mimeType)

    tests whether this data flavor has the given MIME type.

  • String getHumanPresentableName()

    returns the human-presentable name for the data format of this data flavor.

  • Class getRepresentationClass()

    returns a Class object that represents the class of the object that a transferable object will return when called with this data flavor. This is either the class parameter of the MIME type or InputStream.


 java.awt.datatransfer.Clipboard 1.1 

  • DataFlavor[] getAvailableDataFlavors() 5.0

    returns an array of the available flavors.

  • void addFlavorListener(FlavorListener listener) 5.0

    adds a listener that is notified when the set of available flavors changes.


 java.awt.datatransfer.Transferable 1.1 

  • DataFlavor[] getTransferDataFlavors()

    returns an array of the supported flavors.


 java.awt.datatransfer.FlavorListener 5.0 

  • void flavorsChanged(FlavorEvent event)

    is called when a clipboard's set of available flavors changes.

Building an Image Transferable

Objects that you want to transfer via the clipboard must implement the transferable interface. The StringSelection class is currently the only public class in the Java standard library that implements the transferable interface. In this section, you will see how to transfer images into the clipboard. Because the JDK does not supply a class for image transfer, you must implement it yourself.

The class is completely trivial. It simply reports that the only available data format is DataFlavor.imageFlavor, and it holds an image object.

 class ImageSelection implements Transferable {    public ImageSelection(Image image)    {       theImage = image;    }    public DataFlavor[] getTransferDataFlavors()    {       return new DataFlavor[] { DataFlavor.imageFlavor };    }    public boolean isDataFlavorSupported(DataFlavor flavor)    {       return flavor.equals(DataFlavor.imageFlavor);    }    public Object getTransferData(DataFlavor flavor)       throws UnsupportedFlavorException    {       if(flavor.equals(DataFlavor.imageFlavor))       {          return theImage;       }       else       {          throw new UnsupportedFlavorException(flavor);       }    }    private Image theImage; } 

NOTE

The JDK supplies the DataFlavor.imageFlavor constant and does all the heavy lifting to convert between Java images and native clipboard images. But, curiously, it does not supply the wrapper class that is necessary to place images onto the clipboard.


The program of Example 7-17 demonstrates the transfer of images between a Java application and the system clipboard. When the program starts, it generates a Mandelbrot image. Click the Copy button to copy the image to the clipboard and then paste it into another application. (See Figure 7-47.) From another application, copy an image into the system clipboard. Then click the Paste button and see the image being pasted into the example program. (See Figure 7-48.)

Figure 7-47. Copying from a Java program to a native program


Figure 7-48. Copying from a native program to a Java program


The program is a straightforward modification of the text transfer program. The data flavor is now DataFlavor.imageFlavor, and we use the ImageSelection class to transfer an image to the system clipboard.

Example 7-17. ImageTransferTest.java

[View full width]

   1. import java.io.*;   2. import java.awt.*;   3. import java.awt.datatransfer.*;   4. import java.awt.event.*;   5. import java.awt.image.*;   6. import javax.swing.*;   7.   8. /**   9.    This program demonstrates the transfer of images between a Java application  10.    and the system clipboard.  11. */  12. public class ImageTransferTest  13. {  14.    public static void main(String[] args)  15.    {  16.       JFrame frame = new ImageTransferFrame();  17.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  18.       frame.setVisible(true);  19.    }  20. }  21.  22. /**  23.    This frame has an image label and buttons for copying and pasting an image.  24. */  25. class ImageTransferFrame extends JFrame  26. {  27.    public ImageTransferFrame()  28.    {  29.       setTitle("ImageTransferTest");  30.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  31.  32.       label = new JLabel();  33.       image = makeMandelbrot(DEFAULT_WIDTH, DEFAULT_HEIGHT);  34.       label.setIcon(new ImageIcon(image));  35.       add(new JScrollPane(label), BorderLayout.CENTER);  36.       JPanel panel = new JPanel();  37.  38.       JButton copyButton = new JButton("Copy");  39.       panel.add(copyButton);  40.       copyButton.addActionListener(new  41.          ActionListener()  42.          {  43.             public void actionPerformed(ActionEvent event) { copy(); }  44.          });  45.  46.       JButton pasteButton = new JButton("Paste");  47.       panel.add(pasteButton);  48.       pasteButton.addActionListener(new  49.          ActionListener()  50.          {  51.             public void actionPerformed(ActionEvent event) { paste(); }  52.          });  53.  54.       add(panel, BorderLayout.SOUTH);  55.    }  56.  57.    /**  58.       Copies the current image to the system clipboard.  59.    */  60.    private void copy()  61.    {  62.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  63.       ImageSelection selection = new ImageSelection(image);  64.       clipboard.setContents(selection, null);  65.    }  66.  67.    /**  68.       Pastes the image from the system clipboard into the  69.       image label.  70.    */  71.    private void paste()  72.    {  73.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  74.       DataFlavor flavor = DataFlavor.imageFlavor;  75.       if (clipboard.isDataFlavorAvailable(flavor))  76.       {  77.          try  78.          {  79.             image = (Image) clipboard.getData(flavor);  80.             label.setIcon(new ImageIcon(image));  81.          }  82.          catch (UnsupportedFlavorException exception)  83.          {  84.             JOptionPane.showMessageDialog(this, exception);  85.          }  86.          catch (IOException exception)  87.          {  88.             JOptionPane.showMessageDialog(this, exception);  89.          }  90.       }  91.    }  92.  93.    /**  94.       Makes the Mandelbrot image.  95.       @param width the width  96.       @parah height the height  97.       @return the image  98.    */  99.    public BufferedImage makeMandelbrot(int width, int height) 100.    { 101.       BufferedImage image = new BufferedImage(width, height, BufferedImage .TYPE_INT_ARGB); 102.       WritableRaster raster = image.getRaster(); 103.       ColorModel model = image.getColorModel(); 104. 105.       Color fractalColor = Color.red; 106.       int argb = fractalColor.getRGB(); 107.       Object colorData = model.getDataElements(argb, null); 108. 109.       for (int i = 0; i < width; i++) 110.          for (int j = 0; j < height; j++) 111.          { 112.             double a = XMIN + i * (XMAX - XMIN) / width; 113.             double b = YMIN + j * (YMAX - YMIN) / height; 114.             if (!escapesToInfinity(a, b)) 115.                raster.setDataElements(i, j, colorData); 116.          } 117.       return image; 118.    } 119. 120.    private boolean escapesToInfinity(double a, double b) 121.    { 122.       double x = 0.0; 123.       double y = 0.0; 124.       int iterations = 0; 125.       do 126.       { 127.          double xnew = x * x - y * y + a; 128.          double ynew = 2 * x * y + b; 129.          x = xnew; 130.          y = ynew; 131.          iterations++; 132.          if (iterations == MAX_ITERATIONS) return false; 133.       } 134.       while (x <= 2 && y <= 2); 135.       return true; 136.    } 137. 138.    private JLabel label; 139.    private Image image; 140. 141.    private static final double XMIN = -2; 142.    private static final double XMAX = 2; 143.    private static final double YMIN = -2; 144.    private static final double YMAX = 2; 145.    private static final int MAX_ITERATIONS = 16; 146. 147.    private static final int DEFAULT_WIDTH = 300; 148.    private static final int DEFAULT_HEIGHT = 300; 149. } 150. 151. /** 152.    This class is a wrapper for the data transfer of image 153.    objects. 154. */ 155. class ImageSelection implements Transferable 156. { 157.    /** 158.       Constructs the selection. 159.       @param image an image 160.    */ 161.    public ImageSelection(Image image) 162.    { 163.       theImage = image; 164.    } 165. 166.    public DataFlavor[] getTransferDataFlavors() 167.    { 168.       return new DataFlavor[] { DataFlavor.imageFlavor }; 169.    } 170. 171.    public boolean isDataFlavorSupported(DataFlavor flavor) 172.    { 173.       return flavor.equals(DataFlavor.imageFlavor); 174.    } 175. 176.    public Object getTransferData(DataFlavor flavor) 177.       throws UnsupportedFlavorException 178.    { 179.       if(flavor.equals(DataFlavor.imageFlavor)) 180.       { 181.          return theImage; 182.       } 183.       else 184.       { 185.          throw new UnsupportedFlavorException(flavor); 186.       } 187.    } 188. 189.    private Image theImage; 190. } 

Using a Local Clipboard to Transfer Object References

Suppose you want to copy and paste a data type that isn't one of the data types supported by the system clipboard. For example, in a drawing program, you may want to allow your users to copy and paste arbitrary shapes.

The program in Example 7-18 demonstrates this capability. As you can see in Figure 7-49, the program displays two panels. By moving the rectangle "grabbers" in the left panel, you can change the shape of a cubic curve. The panel on the right side can display an arbitrary shape.

Figure 7-49. Transferring local objects


When you click the Copy button, the current cubic curve shape is copied. Click Paste, and the Shape object on the clipboard is displayed in the panel on the right-hand side. You can see that the shape is held on a clipboard by the actions of copying a curve and then modifying the curve before pasting. The copied shape, and not the current shape of the curve, is pasted into the right-side panel.

To transfer an arbitrary Java object reference within the same JVM, you use the MIME type


application/x-java-jvm-local-objectref;class=className

However, the JDK doesn't include a transferable wrapper for this type. You can find the code for the wrapper in the example program. It is entirely analogous to the ImageSelection wrapper of the preceding section.

An object reference is only meaningful within a single virtual machine. For that reason, you cannot copy the shape object to the system clipboard. Instead, this program uses a local clipboard:

 Clipboard clipboard = new Clipboard("local"); 

The construction parameter is the clipboard name.

However, using a local clipboard has one major disadvantage. You need to synchronize the local and the system clipboard, so that users don't confuse the two. Currently, the Java platform doesn't do that synchronization for you.

Example 7-18. LocalTransferTest.java

[View full width]

   1. import java.awt.*;   2. import java.awt.datatransfer.*;   3. import java.awt.event.*;   4. import java.awt.geom.*;   5. import java.io.*;   6. import java.util.*;   7. import javax.swing.*;   8.   9. /**  10.    This program demonstrates the transfer of object references within the same  virtual machine.  11. */  12. public class LocalTransferTest  13. {  14.    public static void main(String[] args)  15.    {  16.       JFrame frame = new LocalTransferFrame();  17.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  18.       frame.setVisible(true);  19.    }  20. }  21.  22. /**  23.    This frame contains a panel to edit a cubic curve, a  24.    panel that can display an arbitrary shape, and copy and  25.    paste buttons.  26. */  27. class LocalTransferFrame extends JFrame  28. {  29.    public LocalTransferFrame()  30.    {  31.       setTitle("LocalTransferTest");  32.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  33.  34.       curvePanel = new CubicCurvePanel();  35.       curvePanel.setPreferredSize(new Dimension(DEFAULT_WIDTH / 2, DEFAULT_HEIGHT));  36.       shapePanel = new ShapePanel();  37.  38.       add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, curvePanel, shapePanel),  39.          BorderLayout.CENTER);  40.       JPanel panel = new JPanel();  41.  42.       JButton copyButton = new JButton("Copy");  43.       panel.add(copyButton);  44.       copyButton.addActionListener(new  45.          ActionListener()  46.          {  47.             public void actionPerformed(ActionEvent event)  48.             {  49.                copy();  50.             }  51.          });  52.  53.       JButton pasteButton = new JButton("Paste");  54.       panel.add(pasteButton);  55.       pasteButton.addActionListener(new  56.          ActionListener()  57.          {  58.             public void actionPerformed(ActionEvent event)  59.             {  60.                paste();  61.             }  62.          });  63.  64.       add(panel, BorderLayout.SOUTH);  65.    }  66.  67.    /**  68.       Copies the current cubic curve to the local clipboard.  69.    */  70.    private void copy()  71.    {  72.       LocalSelection selection = new LocalSelection(curvePanel.getShape());  73.       clipboard.setContents(selection, null);  74.    }  75.  76.    /**  77.       Pastes the shape from the local clipboard into the  78.       shape panel.  79.    */  80.    private void paste()  81.    {  82.       try  83.       {  84.          DataFlavor flavor  85.             = new DataFlavor("application/x-java-jvm-local-objectref;class=java.awt .Shape");  86.          if (clipboard.isDataFlavorAvailable(flavor))  87.             shapePanel.setShape((Shape) clipboard.getData(flavor));  88.       }  89.       catch (ClassNotFoundException e)  90.       {  91.          JOptionPane.showMessageDialog(this, e);  92.       }  93.       catch (UnsupportedFlavorException e)  94.       {  95.          JOptionPane.showMessageDialog(this, e);  96.       }  97.       catch (IOException e)  98.       {  99.          JOptionPane.showMessageDialog(this, e); 100.       } 101.    } 102. 103.    private CubicCurvePanel curvePanel; 104.    private ShapePanel shapePanel; 105.    private Clipboard clipboard = new Clipboard("local"); 106. 107.    private static final int DEFAULT_WIDTH = 300; 108.    private static final int DEFAULT_HEIGHT = 300; 109. } 110. 111. 112. /** 113.    This panel draws a shape and allows the user to 114.    move the points that define it. 115. */ 116. class CubicCurvePanel extends JPanel 117. { 118.    public CubicCurvePanel() 119.    { 120.       addMouseListener(new 121.          MouseAdapter() 122.          { 123.             public void mousePressed(MouseEvent event) 124.             { 125.                for (int i = 0; i < p.length; i++) 126.                { 127.                   double x = p[i].getX() - SIZE / 2; 128.                   double y = p[i].getY() - SIZE / 2; 129.                   Rectangle2D r = new Rectangle2D.Double(x, y, SIZE, SIZE); 130.                   if (r.contains(event.getPoint())) 131.                   { 132.                      current = i; 133.                      return; 134.                   } 135.                } 136.             } 137. 138.             public void mouseReleased(MouseEvent event) 139.             { 140.                current = -1; 141.             } 142.          }); 143. 144.       addMouseMotionListener(new 145.          MouseMotionAdapter() 146.          { 147.             public void mouseDragged(MouseEvent event) 148.             { 149.                if (current == -1) return; 150.                p[current] = event.getPoint(); 151.                repaint(); 152.             } 153.          }); 154. 155.       current = -1; 156.    } 157. 158.    public void paintComponent(Graphics g) 159.    { 160.       super.paintComponent(g); 161.       Graphics2D g2 = (Graphics2D)g; 162.       for (int i = 0; i < p.length; i++) 163.       { 164.          double x = p[i].getX() - SIZE / 2; 165.          double y = p[i].getY() - SIZE / 2; 166.          g2.fill(new Rectangle2D.Double(x, y, SIZE, SIZE)); 167.       } 168. 169.       g2.draw(getShape()); 170.    } 171. 172.    /** 173.       Gets the current cubic curve. 174.       @return the curve shape 175.    */ 176.    public Shape getShape() 177.    { 178.       return new CubicCurve2D.Double(p[0].getX(), p[0].getY(), p[1].getX(), p[1].getY(), 179.          p[2].getX(), p[2].getY(), p[3].getX(), p[3].getY()); 180.    } 181. 182.    private Point2D[] p = 183.    { 184.       new Point2D.Double(10, 10), 185.       new Point2D.Double(10, 100), 186.       new Point2D.Double(100, 10), 187.       new Point2D.Double(100, 200) 188.    }; 189.    private static int SIZE = 10; 190.    private int current; 191. } 192. 193. /** 194.    This panel displays an arbitrary shape. 195. */ 196. class ShapePanel extends JPanel 197. { 198.    /** 199.       Set the shape to be displayed in this panel. 200.       @param aShape any shape 201.    */ 202.    public void setShape(Shape aShape) 203.    { 204.       shape = aShape; 205.       repaint(); 206.    } 207. 208.    public void paintComponent(Graphics g) 209.    { 210.       super.paintComponent(g); 211.       Graphics2D g2 = (Graphics2D) g; 212.       if (shape != null) g2.draw(shape); 213.    } 214. 215.    private Shape shape; 216. } 217. 218. /** 219.    This class is a wrapper for the data transfer of 220.    object references that are transferred within the same 221.    virtual machine. 222. */ 223. class LocalSelection implements Transferable 224. { 225.    /** 226.       Constructs the selection. 227.       @param o any object 228.    */ 229.    LocalSelection(Object o) 230.    { 231.       obj = o; 232.    } 233. 234.    public DataFlavor[] getTransferDataFlavors() 235.    { 236.       DataFlavor[] flavors = new DataFlavor[1]; 237.       Class type = obj.getClass(); 238.       String mimeType = "application/x-java-jvm-local-objectref;application".equals(flavor.getPrimaryType()) 253.          && "x-java-jvm-local-objectref".equals(flavor.getSubType()) 254.          && flavor.getRepresentationClass().isAssignableFrom(obj.getClass()); 255.    } 256. 257.    public Object getTransferData(DataFlavor flavor) 258.       throws UnsupportedFlavorException 259.    { 260.       if (! isDataFlavorSupported(flavor)) 261.          throw new UnsupportedFlavorException(flavor); 262. 263.       return obj; 264.    } 265. 266.    private Object obj; 267. } 


 java.awt.datatransfer.Clipboard 1.1 

  • Clipboard(String name)

    constructs a local clipboard with the given name.

Transferring Java Objects via the System Clipboard

Suppose you want to copy and paste objects from one Java application to another. In that case, you cannot use local clipboards. Fortunately, you can place serialized Java objects onto the system clipboard.

The program in Example 7-19 demonstrates this capability. The program shows a color chooser. The Copy button copies the current color to the system clipboard as a serialized Color object. The Paste button checks whether the system clipboard contains a serialized Color object. If so, it fetches the color and sets it as the current choice of the color chooser.

You can transfer the serialized object between two Java applications (see Figure 7-50). Run two copies of the SerialTransferTest program. Click Copy in the first program, then click Paste in the second program. The Color object is transferred from one virtual machine to the other.

Figure 7-50. Data are copied between two instances of a Java application


To enable the data transfer, the Java platform places binary data on the system clipboard that contains the serialized object. Another Java programnot necessarily of the same type as the one that generated the clipboard datacan retrieve the clipboard data and deserialize the object.

Of course, a non-Java application will not know what to do with the clipboard data. For that reason, the example program offers the clipboard data in a second flavor, as text. The text is simply the result of the toString method, applied to the transferred object. To see the second flavor, run the program, click on a color, and then select the Paste command in your text editor. A string such as

 java.awt.Color[r=255,g=51,b=51] 

will be inserted into your document.

Essentially no additional programming is required to transfer a serializable object. You use the MIME type


application/x-java-serialized-object;class=className

As before, you have to build your own transfer wrappersee the example code for details.

Example 7-19. SerialTransferTest.java

[View full width]

   1. import java.io.*;   2. import java.awt.*;   3. import java.awt.datatransfer.*;   4. import java.awt.event.*;   5. import java.awt.image.*;   6. import javax.swing.*;   7.   8. /**   9.    This program demonstrates the transfer of serialized objects between virtual machines.  10. */  11. public class SerialTransferTest  12. {  13.    public static void main(String[] args)  14.    {  15.       JFrame frame = new SerialTransferFrame();  16.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  17.       frame.setVisible(true);  18.    }  19. }  20.  21. /**  22.    This frame contains a color chooser, and copy and paste buttons.  23. */  24. class SerialTransferFrame extends JFrame  25. {  26.    public SerialTransferFrame()  27.    {  28.       setTitle("SerialTransferTest");  29.  30.       chooser = new JColorChooser();  31.       add(chooser, BorderLayout.CENTER);  32.       JPanel panel = new JPanel();  33.  34.       JButton copyButton = new JButton("Copy");  35.       panel.add(copyButton);  36.       copyButton.addActionListener(new  37.          ActionListener()  38.          {  39.             public void actionPerformed(ActionEvent event)  40.             {  41.                copy();  42.             }  43.          });  44.  45.       JButton pasteButton = new JButton("Paste");  46.       panel.add(pasteButton);  47.       pasteButton.addActionListener(new  48.          ActionListener()  49.          {  50.             public void actionPerformed(ActionEvent event)  51.             {  52.                paste();  53.             }  54.          });  55.  56.       add(panel, BorderLayout.SOUTH);  57.       pack();  58.    }  59.  60.    /**  61.       Copies the chooser's color into the system clipboard.  62.    */  63.    private void copy()  64.    {  65.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  66.       Color color = chooser.getColor();  67.       SerialSelection selection = new SerialSelection(color);  68.       clipboard.setContents(selection, null);  69.    }  70.  71.    /**  72.       Pastes the color from the system clipboard into the chooser.  73.    */  74.    private void paste()  75.    {  76.       Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();  77.       try  78.       {  79.          DataFlavor flavor  80.             = new DataFlavor("application/x-java-serialized-object;class=java.awt .Color");  81.          if (clipboard.isDataFlavorAvailable(flavor))  82.          {  83.             Color color = (Color) clipboard.getData(flavor);  84.             chooser.setColor(color);  85.          }  86.       }  87.       catch (ClassNotFoundException e)  88.       {  89.          JOptionPane.showMessageDialog(this, e);  90.       }  91.       catch (UnsupportedFlavorException e)  92.       {  93.          JOptionPane.showMessageDialog(this, e);  94.       }  95.       catch (IOException e)  96.       {  97.          JOptionPane.showMessageDialog(this, e);  98.       }  99.    } 100. 101.    private JColorChooser chooser; 102. } 103. 104. /** 105.    This class is a wrapper for the data transfer of serialized objects. 106. */ 107. class SerialSelection implements Transferable 108. { 109.    /** 110.       Constructs the selection. 111.       @param o any serializable object 112.    */ 113.    SerialSelection(Serializable o) 114.    { 115.       obj = o; 116.    } 117. 118.    public DataFlavor[] getTransferDataFlavors() 119.    { 120.       DataFlavor[] flavors = new DataFlavor[2]; 121.       Class type = obj.getClass(); 122.       String mimeType = "application/x-java-serialized-object;application".equals(flavor.getPrimaryType()) 140.          && "x-java-serialized-object".equals(flavor.getSubType()) 141.          && flavor.getRepresentationClass().isAssignableFrom(obj.getClass()); 142.    } 143. 144.    public Object getTransferData(DataFlavor flavor) 145.       throws UnsupportedFlavorException 146.    { 147.       if (!isDataFlavorSupported(flavor)) 148.          throw new UnsupportedFlavorException(flavor); 149. 150.       if (DataFlavor.stringFlavor.equals(flavor)) 151.          return obj.toString(); 152. 153.       return obj; 154.    } 155. 156.    private Serializable obj; 157. } 



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net