Java中如何向系统剪贴板写入富文本

当复制了一段richText时,可以在word中粘贴保留有原格式的richText,或者去除了格式信息的plainText;而在notepad中执行粘贴操作时,richText中的格式信息将被过滤,得到的是richText去除格式信息之后的plainText。

问题:

这段richText是以什么样的形式保存在剪贴板中?

执行粘贴操作时应用程序又是如何从剪贴板中取出需要的信息,拆分richText中的格式信息和plainText的呢?


1 java中如何向系统剪贴板写入一段plainText。

这是最基本的Clipboard操作,操作非常直观,java API已经直接提供了白痴级的支持:

    	Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    	StringSelection stringSelection = new StringSelection("plainText");
    	systemClipboard.setContents(stringSelection, null);

2 java中如何向系统剪贴板写入一段richText。

事情总是如此,初识时美好,当进一步了解时,便会有障碍。

当我们对Clipboard的操作有了新的要求,便只能硬着头皮去掌握应用程序和Clipboard之间的数据传输原理。怎么学习呢,网上资料不算多,最好不过还是直接看API了,但问题在于API向来言简意赅,这一段的API更是比较晦涩,而其中一些类、方法的实现方式与本人的代码习惯很是不符,看起来很是不能理解。

软件包 java.awt.datatransfer 

提供在应用程序之间和在应用程序内部传输数据的接口和类,接口和类不算多,基础的、重要的有2个:

public interface Transferable
定义为传输操作提供数据所使用的类的接口,我们要在剪贴板和应用程序之间传输的数据就是放在这玩意中了。

public class DataFlavor
extends Object
implements Externalizable, Cloneable
DataFlavor 提供有关数据的元信息。DataFlavor 通常用于访问剪切板上的数据,或者在执行拖放操作时使用。

我们要传输的数据存储于Transferable对象之中,如何存储?

Transferable是一个接口,在此接口的具体实现中,我们要传输的数据便可作为类的属性存储其中。

如何取出?

这是问题的难点。在从Transferable中取出数据的过程中,我认为DataFlavor将扮演一个存储数据的标识和解析器的角色:作为标识,Transferable会根据应用程序提供的DataFlavor类型向应用程序返回特定的数据,在某种情况下,你可以认为DataFlavor和存储数据之间存在映射关系;作为解析器,当应用程序从Transferable中取得数据之后,将同时使用提取数据时传入Transferable的DataFlavor来进行数据解析,在同一个JVM中,这是容易处理的,当在不同的JVM,或者JVM和本地应用程序之间传输数据时,这意味着JVM的DataFlavor和系统的DataFlavor存在一种映射关系。


直接上例子:

package com.dancen.test;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

/**
 * 剪贴板操作示例
 * 
 * @author Dancen
 *
 */
public class ClipboardDemo
{
	public static void main(String[] args)
	{
		try
		{
			Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
			Transferable transferable = new TextTransferable("<html><body><font color=FF0000>richText</font></body></html>", "plainText");
			systemClipboard.setContents(transferable, null);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

class TextTransferable implements Transferable
{
	public final static DataFlavor PLAIN_TEXT_DF;
	public final static DataFlavor RICH_TEXT_DF;
	
	private final static DataFlavor[] DFS;
	
	private String richText;
	private String plainText;
	
	static
	{
		PLAIN_TEXT_DF = DataFlavor.stringFlavor;
		RICH_TEXT_DF = new DataFlavor("text/html; charset=unicode; class=java.lang.String", "text/html");
		DFS = new DataFlavor[]{PLAIN_TEXT_DF, RICH_TEXT_DF};
	}
	
	public TextTransferable(String richText, String plainText)
	{
		if(null == plainText)
		{
			throw new IllegalArgumentException("the plainText can not be null");
		}
		
		if(null == richText)
		{
			richText = plainText;
		}
		
		this.richText = richText;
		this.plainText = plainText;
	}
	
	@Override
	public boolean isDataFlavorSupported(DataFlavor dataFlavor)
	{
		boolean rs = false;
		
		for(DataFlavor df : DFS)
		{
			if(df.equals(dataFlavor))
			{
				rs = true;
				
				break;
			}
		}
		
		return rs;
	}
	
	@Override
	public DataFlavor[] getTransferDataFlavors()
	{
		return DFS.clone();
	}
	
	@Override
	public Object getTransferData(DataFlavor dataFlavor) throws UnsupportedFlavorException, IOException
	{
		String rs = null;
		
		if(PLAIN_TEXT_DF.equals(dataFlavor))
		{
			rs = this.plainText;
		}
		else if(RICH_TEXT_DF.equals(dataFlavor))
		{
			rs = this.richText;
		}
		else
		{
			throw new UnsupportedFlavorException(dataFlavor);
		}
		
		return rs;
	}
}

执行以上示例之后,在word中执行粘贴操作,将贴入红色的“richText”,在notePad中执行粘贴操作,将贴入“plainText”,很显然,微软这些应用程序会自觉地根据自己的牛逼程度从剪贴板种选择并获取数据。

你可能感兴趣的:(Java中如何向系统剪贴板写入富文本)