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类的代码。