支持对象的剪切板

7 篇文章 0 订阅

前一阵做JTextPane的东西,一直不知道剪切板怎么用。后来研究了一下,知道怎么用剪切板分别复制粘贴文字和图像了。但是如果要同时复制图像和文字就不会了。

看了半天API,应该是支持剪切对象的,但是不知道具体怎么操作。后来看了一下《Java核心技术 卷2 原书第八版》中的内容(P558),按照上面的代码修改了一下,终于能够剪切和粘贴图文混排的内容了。


代码如下:

package cn.com.microproposal.test.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

/**
 * 转载请注明出处。Blog : http://blog.csdn.net/levelmini/article/details/27661703
 * @author Aranya
 *
 */
public class SerialTransferTest {
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable(){
			public void run(){
				JFrame frame = new SerialTransferFrame();
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setVisible(true);
			}
		});
	}
}

class SerialTransferFrame extends JFrame {

	private static final long serialVersionUID = 6239828970658861018L;
	
	private JTextPane textpane;
	public SerialTransferFrame() {
		textpane = new JTextPane();
		add(textpane,BorderLayout.CENTER);
		JPanel panel = new JPanel();
		
		JButton copy = new JButton("Copy");
		panel.add(copy);
		JButton paste = new JButton("Paste");
		panel.add(paste);
		copy.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				copy();
			}
		});
		paste.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				paste();
			}
		});
		add(panel,BorderLayout.SOUTH);
		pack();
	}
	
	private void copy() {
		Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
		
		int start = textpane.getSelectionStart();
		int end = textpane.getSelectionEnd();
		
		if (start == end) {  //如果相等则说明没有选中任何内容
			return;
		}
		//将选中的内容封装到对象中
		StyledDocument doc = textpane.getStyledDocument();
		MyImgAndTextObject object = new MyImgAndTextObject();
		for (int i = start; i < end; i++) {
			Element el = doc.getCharacterElement(i);
			if (el.getName().equals("content")) {
				try {
					object.put(textpane.getText(i, 1));
				} catch (BadLocationException e) {
					e.printStackTrace();
				}
			}
			if (el.getName().equals("icon")) {
				Icon icon = StyleConstants.getIcon(el.getAttributes());
				object.put(icon);				
			}
		}
		
		SerialTransferable selection = new SerialTransferable(object);
		clipboard.setContents(selection, null);
	}
	
	private void paste() {
		Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
		StyledDocument doc = textpane.getStyledDocument(); 
		int start = textpane.getSelectionStart();
		int end = textpane.getSelectionEnd();
		try {
			if (start < end) {	//如果有选中的数据则移除选中的数据
				doc.remove(start, end-start);
			}
			DataFlavor img_flavor = DataFlavor.imageFlavor;
			DataFlavor text_flavor = DataFlavor.stringFlavor; 
			DataFlavor obj_flavor = new DataFlavor("application/x-java-serialized-object;class=cn.com.microproposal.test.gui.MyImgAndTextObject");
			if (clipboard.isDataFlavorAvailable(obj_flavor)) {	//这个判断一定要写在前面,否则会多粘贴出来东西。
				MyImgAndTextObject object = (MyImgAndTextObject) clipboard.getData(obj_flavor);
				int i = 0;
				for (Object obj : object) {
					if (obj instanceof String) {
						doc.insertString(start+i, obj+"", null);
					}
					if (obj instanceof ImageIcon) {
						textpane.insertIcon((ImageIcon)obj);
					}
					i++;
				}
			}else if (clipboard.isDataFlavorAvailable(img_flavor)) {
				BufferedImage img = (BufferedImage) clipboard.getData(img_flavor);
				Icon icon = new ImageIcon(img);
				textpane.insertIcon(icon);
			} else if (clipboard.isDataFlavorAvailable(text_flavor)) {
				String str = (String) clipboard.getData(text_flavor);
				doc.insertString(start, str, null);
			} 
		} catch (ClassNotFoundException e) {
			JOptionPane.showMessageDialog(this, e);
		} catch (UnsupportedFlavorException e) {
			JOptionPane.showMessageDialog(this, e);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}

	}
}

/**
 * 支持传输对象的Transfer
 * @author Aranya
 */
class SerialTransferable implements Transferable {

	Object obj ;
	public SerialTransferable(Serializable o) {
		obj = o;
	}
	
	@Override
	public DataFlavor[] getTransferDataFlavors() {
		DataFlavor [] flavors = new DataFlavor[2];
		Class<?> type = obj.getClass();
		String mimeType = "application/x-java-serialized-object;class="+type.getName();
		try {
			flavors[0] = new DataFlavor(mimeType);
			flavors[1] = DataFlavor.stringFlavor;
			return flavors;
		} catch (ClassNotFoundException e) {
			return new DataFlavor[0];
		}
		
	}

	@Override
	public boolean isDataFlavorSupported(DataFlavor flavor) {
		return DataFlavor.stringFlavor.equals(flavor)
				|| "application".equals(flavor.getPrimaryType())
				&& "x-java-serialized-object".equals(flavor.getSubType())
				&&flavor.getRepresentationClass().isAssignableFrom(obj.getClass());
	}

	@Override
	public Object getTransferData(DataFlavor flavor)
			throws UnsupportedFlavorException, IOException {
		if (!isDataFlavorSupported(flavor)) {
			throw new UnsupportedFlavorException(flavor);
		}
		if (DataFlavor.stringFlavor.equals(flavor)) {
			return obj.toString();
		}
		return obj;
	}
}
/**
 * 封装图文的对象
 * @author Aranya
 */
class MyImgAndTextObject implements Serializable,Iterable<Object>{

	private static final long serialVersionUID = -4660396449705937711L;
	
	private List<Object> content = new ArrayList<Object>();
	
	public boolean put(Object o){
		return content.add(o);
	}
	public List<Object> get(){
		return content;
	}
	@Override
	public Iterator<Object> iterator() {
		return content.iterator();
	}
}


扩展:自己写一个类继承JTextPane,然后Override这个类的copy()方法和paste()方法,实现步骤就按照这里面的copy()方法和paste()方法,就可以让你的TextPane带有对应的功能了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值