11.9.5 通过系统剪贴板传递Java对象
11.9.5 通过系统剪贴板传递Java对象
系统剪贴板不仅支持传输文本、图像的基本内容,而且支持传输序列化的Java对象和远程对象,复制到剪贴板中的序列化的Java对象和远程对象可以使用另一个Java程序(不在同一个虚拟机内的程序)来读取。DataFlavor中提供了javaSerializedObjectMimeType、javaRemoteObjectMimeType两个字符串常量来表示序列化的Java对象和远程对象的MIME类型,这两种MIME类型提供了复制对象、读取对象所包含的复杂操作,程序只需创建对应的Tranferable实现类即可。
提示:
关于对象序列化请参考本书第15章的介绍——如果某个类是可序列化的,则该类的实例可以转换成二进制流,从而可以将该对象通过网络传输或保存到磁盘上。为了保证某个类是可序列化的,只要让该类实现Serializable接口即可。
下面程序实现了一个SerialSelection类,该类与前面的ImageSelection、LocalObjectSelection实现类相似,都需要实现Tranferable接口,实现该接口的三个方法,并持有一个可序列化的对象。
import java.awt.datatransfer.*; import java.io.*; public class SerialSelection implements Transferable { // 持有一个可序列化的对象 private Serializable obj; // 创建该类的对象时传入被持有的对象 public SerialSelection(Serializable obj) { this.obj = obj; } public DataFlavor[] getTransferDataFlavors() { DataFlavor[] flavors = new DataFlavor[2]; // 获取被封装对象的类型 Class clazz = obj.getClass(); try { flavors[0] = new DataFlavor(DataFlavor.javaSerializedObjectMimeType + ";class=" + clazz.getName()); flavors[1] = DataFlavor.stringFlavor; return flavors; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if(!isDataFlavorSupported(flavor)) { throw new UnsupportedFlavorException(flavor); } if (flavor.equals(DataFlavor.stringFlavor)) { return obj.toString(); } return obj; } public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.stringFlavor) || flavor.getPrimaryType().equals("application") && flavor.getSubType().equals("x-java-serialized-object") && flavor.getRepresentationClass().isAssignableFrom(obj.getClass()); } }
上面程序也创建了一个DataFlavor对象,该对象使用的MIME类型为"application/x-java-serialized-object;class="+clazz.getName()
,它表示封装可序列化的Java对象的数据格式。
有了上面的SerialSelection类后,程序就可以把一个可序列化的对象封装成SerialSelection对象,并将该对象放入系统剪贴板中,另一个Java程序也可以从系统剪贴板中读取该对象。下面复制、读取Dog对象的程序与前面的复制、粘贴Person对象的程序非常相似,只是该程序使用的是系统剪贴板,而不是本地剪贴板。
import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.Label; import java.awt.Panel; import java.awt.TextArea; import java.awt.TextField; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.io.Serializable; class Dog implements Serializable { private String name; private int age; public Dog(){} public Dog(String name , int age) { this.name = name; this.age = age; } // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public String toString() { return "Dog [ name=" + name + " , age=" + age + " ]"; } } public class CopySerializable { Frame f = new Frame("复制对象"); Button copy = new Button("复制"); Button paste = new Button("粘贴"); TextField name = new TextField(15); TextField age = new TextField(15); TextArea ta = new TextArea(3 , 30); // 创建系统剪贴板 Clipboard clipboard = Toolkit.getDefaultToolkit() .getSystemClipboard(); public void init() { Panel p = new Panel(); p.add(new Label("姓名")); p.add(name); p.add(new Label("年龄")); p.add(age); f.add(p , BorderLayout.NORTH); f.add(ta); Panel bp = new Panel(); copy.addActionListener(e -> copyDog()); paste.addActionListener(e -> { try { readDog(); } catch (Exception ee) { ee.printStackTrace(); } }); bp.add(copy); bp.add(paste); f.add(bp , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public void copyDog() { Dog d = new Dog(name.getText() , Integer.parseInt(age.getText())); // 把dog实例封装成SerialSelection对象 SerialSelection ls =new SerialSelection(d); // 把SerialSelection对象放入系统剪贴板中 clipboard.setContents(ls , null); } public void readDog()throws Exception { DataFlavor peronFlavor = new DataFlavor(DataFlavor .javaSerializedObjectMimeType + ";class=Dog"); if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { // 从系统剪贴板中读取数据 Dog d = (Dog)clipboard.getData(peronFlavor); ta.setText(d.toString()); } } public static void main(String[] args) { new CopySerializable().init(); } }
上面程序中的两段粗体字代码实现了复制、粘贴对象的功能,复制时将Dog对象封装成SerialSelection对象后放入剪贴板中;读取时先创建application/x-java-serialized-object;class==Dog类型的DataFlavor,然后从剪贴板中读取对应格式的内容即可。运行上面程序,在“姓名”文本框内输入字符串,在“年龄”文本框内输入数字,单击“复制”按钮,即可将该Dg对象放入系统剪贴板中。
再次运行上面程序(即启动另一个虚拟机),单击窗口中的“粘贴”按钮,将可以看到系统剪贴板中的Dog对象被读取出来,启动系统剪贴板也可以看到被放入剪贴板内的D0g对象,如图11.37所示。
图11.37访问系统剪贴板中的Dog对象
上面的Dog类也非常简单,为了让该类是可序列化的,让该类实现Serializable接口即可。读者可以参考codes\11\11.9\CopySerializable.java文件来查看Dog类的代码。