我从java.sun.com和javaworld.com上的例子改过来的一棵文件系统树,支持拖放,ctrl+v复制文件
import java.awt.alphacomposite;
import java.awt.component;
import java.awt.graphics2d;
import java.awt.point;
import java.awt.rectangle;
import java.awt.toolkit;
import java.awt.datatransfer.dataflavor;
import java.awt.datatransfer.stringselection;
import java.awt.datatransfer.transferable;
import java.awt.datatransfer.unsupportedflavorexception;
import java.awt.dnd.dndconstants;
import java.awt.dnd.draggestureevent;
import java.awt.dnd.draggesturelistener;
import java.awt.dnd.dragsource;
import java.awt.dnd.dragsourcedragevent;
import java.awt.dnd.dragsourcedropevent;
import java.awt.dnd.dragsourceevent;
import java.awt.dnd.dragsourcelistener;
import java.awt.dnd.droptarget;
import java.awt.dnd.droptargetdragevent;
import java.awt.dnd.droptargetdropevent;
import java.awt.dnd.droptargetevent;
import java.awt.dnd.droptargetlistener;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.awt.event.keyadapter;
import java.awt.event.keyevent;
import java.awt.geom.affinetransform;
import java.awt.geom.rectangle2d;
import java.awt.image.bufferedimage;
import java.io.file;
import java.io.fileinputstream;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.util.iterator;
import java.util.list;
import javax.swing.icon;
import javax.swing.jlabel;
import javax.swing.jtree;
import javax.swing.timer;
import javax.swing.event.treeexpansionevent;
import javax.swing.event.treeexpansionlistener;
import javax.swing.filechooser.filesystemview;
import javax.swing.tree.defaultmutabletreenode;
import javax.swing.tree.defaulttreecellrenderer;
import javax.swing.tree.defaulttreemodel;
import javax.swing.tree.treepath;
class dragtree extends jtree implements draggesturelistener,
dragsourcelistener, droptargetlistener {
bufferedimage ghostimage;
private rectangle2d ghostrect = new rectangle2d.float();
private point ptoffset = new point();
private point lastpoint = new point();
private treepath lastpath;
private timer hovertimer;
filenode sourcenode;
public dragtree() {
dragsource dragsource = dragsource.getdefaultdragsource();
dragsource.createdefaultdraggesturerecognizer(this, // component where
// drag originates
dndconstants.action_copy_or_move, // actions
this); // drag gesture recognizer
setmodel(createtreemodel());
addtreeexpansionlistener(new treeexpansionlistener() {
public void treecollapsed(treeexpansionevent e) {
}
public void treeexpanded(treeexpansionevent e) {
treepath path = e.getpath();
if (path != null) {
filenode node = (filenode) path.getlastpathcomponent();
if (!node.isexplored()) {
defaulttreemodel model = (defaulttreemodel) getmodel();
node.explore();
model.nodestructurechanged(node);
}
}
}
});
this.setcellrenderer(new defaulttreecellrenderer() {
public component gettreecellrenderercomponent(jtree tree,
object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasfocus) {
treepath tp = tree.getpathforrow(row);
if (tp != null) {
filenode node = (filenode) tp.getlastpathcomponent();
file f = node.getfile();
try {
icon icon = filesystemview.getfilesystemview()
.getsystemicon(f);
this.seticon(icon);
this.setleaficon(icon);
this.setopenicon(icon);
this.setclosedicon(icon);
this.setdisabledicon(icon);
} catch (exception e) {
e.printstacktrace();
}
}
return super.gettreecellrenderercomponent(tree, value,
selected, expanded, leaf, row, hasfocus);
}
});
super.setscrollsonexpand(true);
new droptarget(this, dndconstants.action_copy_or_move, this);
// set up a hover timer, so that a node will be automatically expanded
// or collapsed
// if the user lingers on it for more than a short time
hovertimer = new timer(1000, new actionlistener() {
public void actionperformed(actionevent e) {
if (lastpath == null) {
return;
}
if (getrowforpath(lastpath) == 0)
return; // do nothing if we are hovering over the root node
if (isexpanded(lastpath))
collapsepath(lastpath);
else
expandpath(lastpath);
}
});
hovertimer.setrepeats(false); // set timer to one-shot mode
this.addkeylistener(new keyadapter() {
public void keypressed(keyevent e) {
int code = e.getkeycode();
int modifiers = e.getmodifiers();
if (code == v || code == v) {
system.out.println("find v");
system.out.println("modifiers:" + modifiers + "\t"
+ ((modifiers & keyevent.ctrl_mask) != 0));
}
if ((modifiers & keyevent.ctrl_mask) != 0
&& (code == v || code == v)) {
transferable tr = toolkit.getdefaulttoolkit()
.getsystemclipboard().getcontents(null);
treepath path = getselectionpath();
if (path == null) {
return;
}
filenode node = (filenode) path.getlastpathcomponent();
if (node.isdirectory()) {
system.out.println("file cp");
try {
list list = (list) (tr
.gettransferdata(dataflavor.javafilelistflavor));
iterator iterator = list.iterator();
file parent = node.getfile();
while (iterator.hasnext()) {
file f = (file) iterator.next();
cp(f, new file(parent, f.getname()));
}
node.reexplore();
} catch (exception ioe) {
ioe.printstacktrace();
}
updateui();
}
}
}
});
}
public void draggesturerecognized(draggestureevent e) {
// drag anything …
treepath path = getleadselectionpath();
if (path == null)
return;
filenode node = (filenode) path.getlastpathcomponent();
sourcenode = node;
// work out the offset of the drag point from the treepath bounding
// rectangle origin
rectangle rapath = getpathbounds(path);
point ptdragorigin = e.getdragorigin();
ptoffset.setlocation(ptdragorigin.x – rapath.x, ptdragorigin.y
– rapath.y);
// get the cell renderer (which is a jlabel) for the path being dragged
int row = this.getrowforlocation(ptdragorigin.x, ptdragorigin.y);
jlabel lbl = (jlabel) getcellrenderer().gettreecellrenderercomponent(
this, // tree
path.getlastpathcomponent(), // value
false, // isselected (dont want a colored background)
isexpanded(path), // isexpanded
getmodel().isleaf(path.getlastpathcomponent()), // isleaf
row, // row (not important for rendering)
false // hasfocus (dont want a focus rectangle)
);
lbl.setsize((int) rapath.getwidth(), (int) rapath.getheight()); // <–
// the
// layout
// manager
// would
// normally
// do
// this
// get a buffered image of the selection for dragging a ghost image
this.ghostimage = new bufferedimage((int) rapath.getwidth(),
(int) rapath.getheight(), bufferedimage.type_int_argb_pre);
graphics2d g2 = ghostimage.creategraphics();
// ask the cell renderer to paint itself into the bufferedimage
g2.setcomposite(alphacomposite.getinstance(alphacomposite.src, 0.5f));
// make the image ghostlike
lbl.paint(g2);
g2.dispose();
//this.getgraphics().drawimage(ghostimage, e.getdragorigin().x,
// e.getdragorigin().y, this);
e.startdrag(null, // cursor
ghostimage, new point(5, 5),
new stringselection(getfilename()), // transferable
this); // drag source listener
}
public void dragdropend(dragsourcedropevent e) {
ghostimage = null;
sourcenode = null;
}
public void dragenter(dragsourcedragevent e) {
}
public void dragexit(dragsourceevent e) {
if (!dragsource.isdragimagesupported()) {
repaint(ghostrect.getbounds());
}
}
public void dragover(dragsourcedragevent e) {
}
public void dropactionchanged(dragsourcedragevent e) {
}
public string getfilename() {
treepath path = getleadselectionpath();
filenode node = (filenode) path.getlastpathcomponent();
return ((file) node.getuserobject()).getabsolutepath();
}
private defaulttreemodel createtreemodel() {
file root = filesystemview.getfilesystemview().getroots()[0];
filenode rootnode = new filenode(root);
rootnode.explore();
return new defaulttreemodel(rootnode);
}
public void dragenter(droptargetdragevent dtde) {
}
public void dragover(droptargetdragevent dtde) {
point pt = dtde.getlocation();
if (pt.equals(lastpoint)) {
return;
}
if (ghostimage != null) {
graphics2d g2 = (graphics2d) getgraphics();
// if a drag image is not supported by the platform, then draw my
// own drag image
if (!dragsource.isdragimagesupported()) {
paintimmediately(ghostrect.getbounds()); // rub out the last
// ghost image and cue
// line
// and remember where we are about to draw the new ghost image
ghostrect.setrect(pt.x – ptoffset.x, pt.y – ptoffset.y,
ghostimage.getwidth(), ghostimage.getheight());
g2.drawimage((ghostimage), affinetransform
.gettranslateinstance(ghostrect.getx(), ghostrect
.gety()), null);
}
}
treepath path = getclosestpathforlocation(pt.x, pt.y);
if (!(path == lastpath)) {
lastpath = path;
hovertimer.restart();
}
}
public void dropactionchanged(droptargetdragevent dtde) {
}
public void drop(droptargetdropevent e) {
try {
dataflavor stringflavor = dataflavor.stringflavor;
transferable tr = e.gettransferable();
treepath path = this.getpathforlocation(e.getlocation().x, e
.getlocation().y);
if (path == null) {
e.rejectdrop();
return;
}
filenode node = (filenode) path.getlastpathcomponent();
if (e.isdataflavorsupported(dataflavor.javafilelistflavor)
&& node.isdirectory()) {
e.acceptdrop(dndconstants.action_copy_or_move);
system.out.println("file cp");
list list = (list) (e.gettransferable()
.gettransferdata(dataflavor.javafilelistflavor));
iterator iterator = list.iterator();
file parent = node.getfile();
while (iterator.hasnext()) {
file f = (file) iterator.next();
cp(f, new file(parent, f.getname()));
}
node.reexplore();
e.dropcomplete(true);
this.updateui();
} else if (e.isdataflavorsupported(stringflavor)
&& node.isdirectory()) {
string filename = (string) tr.gettransferdata(stringflavor);
if (filename.endswith(".txt") || filename.endswith(".java")
|| filename.endswith(".jsp")
|| filename.endswith(".html")
|| filename.endswith(".htm")) {
e.acceptdrop(dndconstants.action_copy_or_move);
file f = new file(filename);
if (f.exists()) {
f.renameto(new file(node.getfile(), f.getname()));
node.reexplore();
((filenode) sourcenode.getparent()).remove(sourcenode);
e.dropcomplete(true);
this.updateui();
} else {
e.rejectdrop();
}
} else {
e.rejectdrop();
}
} else {
e.rejectdrop();
}
} catch (ioexception ioe) {
ioe.printstacktrace();
} catch (unsupportedflavorexception ufe) {
ufe.printstacktrace();
} finally {
ghostimage = null;
this.repaint();
}
}
private void cp(file src, file dest) throws ioexception {
if (src.isdirectory()) {
if (!dest.exists()) {
boolean ret = dest.mkdir();
if (ret == false)
return;
}
file[] fs = src.listfiles();
for (int i = 0; i < fs.length; i++) {
cp(fs[i], new file(dest, fs[i].getname()));
}
return;
}
byte[] buf = new byte[1024];
fileinputstream in = new fileinputstream(src);
fileoutputstream out = new fileoutputstream(dest);
int len;
try {
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} finally {
in.close();
out.close();
}
}
public void dragexit(droptargetevent dte) {
}
}
class filenode extends defaultmutabletreenode {
private boolean explored = false;
public filenode(file file) {
setuserobject(file);
}
public boolean getallowschildren() {
return isdirectory();
}
public boolean isleaf() {
return !isdirectory();
}
public file getfile() {
return (file) getuserobject();
}
public boolean isexplored() {
return explored;
}
public boolean isdirectory() {
file file = getfile();
return file.isdirectory();
}
public string tostring() {
file file = (file) getuserobject();
string filename = file.tostring();
int index = filename.lastindexof(file.separator);
return (index != -1 && index != filename.length() – 1) ? filename
.substring(index + 1) : filename;
}
public void explore() {
if (!isdirectory())
return;
if (!isexplored()) {
file file = getfile();
file[] children = file.listfiles();
for (int i = 0; i < children.length; ++i) {
if (children[i].isdirectory())
add(new filenode(children[i]));
}
for (int i = 0; i < children.length; ++i) {
if (!children[i].isdirectory())
add(new filenode(children[i]));
}
explored = true;
}
}
public void reexplore() {
this.removeallchildren();
explored = false;
explore();
}
}
使用方法示例:
import java.awt.borderlayout;
import java.awt.dimension;
import java.awt.datatransfer.dataflavor;
import java.awt.datatransfer.transferable;
import java.awt.datatransfer.unsupportedflavorexception;
import java.awt.dnd.dndconstants;
import java.awt.dnd.droptarget;
import java.awt.dnd.droptargetdragevent;
import java.awt.dnd.droptargetdropevent;
import java.awt.dnd.droptargetevent;
import java.awt.dnd.droptargetlistener;
import java.awt.event.windowadapter;
import java.awt.event.windowevent;
import java.io.file;
import java.io.filereader;
import java.io.ioexception;
import java.util.iterator;
import java.util.list;
import javax.swing.borderfactory;
import javax.swing.jeditorpane;
import javax.swing.jframe;
import javax.swing.jpanel;
import javax.swing.jscrollpane;
import javax.swing.jsplitpane;
import javax.swing.uimanager;
import javax.swing.windowconstants;
import javax.swing.filechooser.filesystemview;
import javax.swing.text.document;
import javax.swing.text.editorkit;
public class test extends jframe implements droptargetlistener {
private jeditorpane textpane = new jeditorpane();
public test() {
super("drag and drop with swing");
new droptarget(textpane, dndconstants.action_copy_or_move, this);
jsplitpane splitpane = new jsplitpane(jsplitpane.horizontal_split,
createtreepanel(), createtextpanel());
splitpane.setdividerlocation(250);
splitpane.setonetouchexpandable(true);
getcontentpane().add(splitpane, borderlayout.center);
}
public static void main(string args[]) {
try {
uimanager.setlookandfeel(uimanager.getsystemlookandfeelclassname());
} catch (exception e1) {
e1.printstacktrace();
}
test test = new test();
test.setbounds(300, 300, 850, 350);
test.setvisible(true);
test.setdefaultcloseoperation(windowconstants.dispose_on_close);
test.addwindowlistener(new windowadapter() {
public void windowclosed(windowevent e) {
system.exit(0);
}
});
}
private jpanel createtreepanel() {
jpanel treepanel = new jpanel();
dragtree tree = new dragtree();
treepanel.setlayout(new borderlayout());
treepanel.add(new jscrollpane(tree), borderlayout.center);
treepanel.setborder(borderfactory
.createtitledborder("drag source for filenames"));
return treepanel;
}
private jpanel createtextpanel() {
jpanel textpanel = new jpanel();
textpanel.setlayout(new borderlayout());
textpanel.add(new jscrollpane(textpane), borderlayout.center);
textpanel.setminimumsize(new dimension(375, 0));
textpanel.setborder(borderfactory
.createtitledborder("drop target for filenames"));
return textpanel;
}
private void readfile(final string filename) {
try {
textpane.setpage(new file(filename).tourl());
} catch (ioexception e) {
editorkit kit = textpane.geteditorkit();
document document = textpane.getdocument();
try {
document.remove(0, document.getlength());
kit.read(new filereader(filename), document, 0);
} catch (exception ex) {
ex.printstacktrace();
}
}
}
public void drop(droptargetdropevent e) {
try {
dataflavor stringflavor = dataflavor.stringflavor;
transferable tr = e.gettransferable();
if (e.isdataflavorsupported(stringflavor)) {
string filename = (string) tr.gettransferdata(stringflavor);
if (filename.endswith(".txt")
|| filename.endswith(".java") ||
filename.endswith(".jsp") || filename.endswith(".html") || filename.endswith(".htm")) {
e.acceptdrop(dndconstants.action_copy_or_move);
readfile(filename);
textpane.setcaretposition(0);
e.dropcomplete(true);
} else {
e.rejectdrop();
}
}
else {
e.rejectdrop();
}
} catch (ioexception ioe) {
ioe.printstacktrace();
} catch (unsupportedflavorexception ufe) {
ufe.printstacktrace();
}
}
public void dragenter(droptargetdragevent e) {
}
public void dragexit(droptargetevent e) {
}
public void dragover(droptargetdragevent e) {
}
public void dropactionchanged(droptargetdragevent e) {
}
}
