[J2SE]JTree使用DefaultTreeModel,对节点进行增删、拖拽和展开操作,以及跨平台文件拖拽的方法详细介绍

一、文件拖拽相关API的实现:

1.1 DnD的实现(DropTargetListener

保留JTreeDnD添加节点方法,继承JTree不变而去掉DropTargetListener的实现改为JTreeUtilsJPanelDnD继承DropTargetListenerdrop方法(说明:标有【*】则表示该Class弃用

* public class JTreeDnD extends JTree implements DropTargetListener {}

public class JTreeUtils extends JTree {}

public class JTreeDnD extends JPanel implements DropTargetListener {}

	@SuppressWarnings("unchecked")
	@Override
	public void drop(DropTargetDropEvent dtde) {
		DataFlavor dataFlavor = DataFlavor.javaFileListFlavor;
		if (dtde.isDataFlavorSupported(dataFlavor)) {
			dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
			List<File> list = null;
			Transferable transferable = dtde.getTransferable();
			try {
				list = (List<File>) transferable.getTransferData(dataFlavor);
			} catch (UnsupportedFlavorException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			addNewUserObjects((DefaultMutableTreeNode) this.getModel().getRoot(), list);
			dtde.dropComplete(true);
		}
	}

二、文件树相关API的实现:

2.1 JTree

jTreeDnD更新为JTreeUtils

jTreeDnD = new JTreeDnD();
jTreeDnD.setShowsRootHandles(true);
jTreeDnD.setDragEnabled(true);
jTreeDnD.setEditable(true);

2.2 DefaultMutableTreeNode

DefaultMutableTreeNode dmTreeNodeRoot = new DefaultMutableTreeNode();
dmTreeNodeRoot.setUserObject("图层");

2.3 DefaultTreeModel

DefaultTreeModel treeModelRoot = new DefaultTreeModel(dmTreeNodeRoot);
jTreeDnD.setModel(treeModelRoot);

 三、子节点的增删,拖拽(增删改查)

3.1 文件读取

private void loadResources(File[] fileArray) {
		jTreeDnD.addNewUserObjects((DefaultMutableTreeNode) ((DefaultTreeModel) jTreeDnD.getModel()).getRoot(),
		fileUtils.toList(fileArray));
}

        前面第一部分有介绍,拖拽使用了list<File>来读取文件,此处沿用了以上方法。

3.2 添加子节点

DefaultTreeModel dtm = (DefaultTreeModel) this.getModel();
for (Iterator<File> iterator = list.iterator(); iterator.hasNext();) {
	File file = (File) iterator.next();
	DefaultMutableTreeNode dmtn = new DefaultMutableTreeNode();
	if (file.isDirectory()) {
		dmtn.setAllowsChildren(true);
	} else {
		dmtn.setAllowsChildren(false);
	}
	dmtn.setUserObject(file);
	dtm.insertNodeInto(dmtn, parent, 0);
}

MutableTreeNode提供的方法:

public void insertNodeInto(MutableTreeNode newChild, MutableTreeNode parent, int index){}

3.3 文件夹展开

        如以上代码片段,对于文件夹须有展开的操作,所以调用了setAllowsChildren(true)方法。

private void expandDirectory(int selRow, TreePath selPath) {
	DefaultMutableTreeNode treeNodeSelected = (DefaultMutableTreeNode) selPath.getLastPathComponent();
	if (null == treeNodeSelected) {
		return;
	}
	Object object = treeNodeSelected.getUserObject();
	if (object instanceof File) {
		File file = (File) object;
		if (file.isDirectory()) {
			jTreeDnD.addNewUserObjects(treeNodeSelected, fileUtils.toList(file.listFiles()));
		}
	}
}

JTreeUtils进行MouseListener监听:

public void mouseClicked(MouseEvent e) {
	int selRow = jTreeUtils.getRowForLocation(e.getX(), e.getY());
	TreePath selPath = jTreeUtils.getPathForLocation(e.getX(), e.getY());
	if (null != selPath) {
		if (selRow != -1) {
			if (e.getButton() == MouseEvent.BUTTON3) {
				myRightClick(selRow, selPath);
			} else if (e.getClickCount() == 2) {
				myDoubleClick(selRow, selPath);
			}
		}
	}
}

(关于选择节点的获取,用上了TreePath,官方API文档介绍了一个监听器,可选用:)

MouseListener ml = new MouseAdapter() {
	public void mousePressed(MouseEvent e) {
	    int selRow = jTreeDnD.getRowForLocation(e.getX(), e.getY());
		TreePath selPath = jTreeDnD.getPathForLocation(e.getX(), e.getY());
		if (selRow != -1) {
			if (e.getClickCount() == 1) {
				mySingleClick(selRow, selPath);
			} else if (e.getClickCount() == 2) {
				myDoubleClick(selRow, selPath);
			}
		}
	}
};
jTreeDnD.addMouseListener(ml);

int selRow = jTreeDnD.getRowForLocation(e.getX(), e.getY());

TreePath selPath = jTreeDnD.getPathForLocation(e.getX(), e.getY());

TreePath selPath = jTreeDnD.getPathForRow(selRow);

获取当前选择的节点:

DefaultMutableTreeNode treeNodeSelected = (DefaultMutableTreeNode) selPath.getLastPathComponent();

3.4 删除节点

DefaultTreeModel dtm = (DefaultTreeModel) jTreeUtils.getModel();
dtm.removeNodeFromParent(treeNodeSelected);

DefaultTreeModel提供的方法:

public void removeNodeFromParent(MutableTreeNode node){}

3.5 拖拽节点

JTreeUtils进行MouseMotionListener监听:

MouseMotionListener mml = new MouseMotionListener() {

	private TreePath draggedPath;
	private TreePath movedPath;

	@Override
	public void mouseDragged(MouseEvent e) {
//		int selRow = jTreeUtils.getRowForLocation(e.getX(), e.getY());
		TreePath selPath = jTreeUtils.getPathForLocation(e.getX(), e.getY());
		if (null != selPath) {
			draggedPath = selPath;
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
	    int selRow = jTreeUtils.getRowForLocation(e.getX(), e.getY());
		TreePath selPath = jTreeUtils.getPathForLocation(e.getX(), e.getY());
		if (null != selPath) {
			movedPath = selPath;
			myNodeMoveTo(selRow, selPath);
		}
	}
}

获得抓取的节点TreePath,以及最后移动停止的节点TreePath,再调用DefaultTreeModel提供的节点增删方法:

dtm.removeNodeFromParent(treeNodeSelected);
dtm.insertNodeInto(treeNodeSelected, parent, 0);
movedPath = null;

注意

        1.关于树状结构节点拖动,个人认为根节点禁止更改,父或祖先节点禁止移动向子节点。

        2.节点抓取或移动状态时,未接触或未抓取节点所获取row值为-1treePath值为null,此处可以根据需要自行用作删除节点,或默认将节点移动并设为根节点的子节点的操作,此处我并未判断为可使用,节点更改位置后我加入了这个方法:

dtm.nodeChanged(treeNodeParent);

3.6 查找节点

        暂未进行研究,待编辑。。。

        以下为项目演示效果图

Java图形化界面:

读取文件:

文件拖拽:

文件夹节点展开:

节点拖动:

 

节点删除:

后记:

        关于JTree相关的一系列操作,很多大佬推荐使用DefaultTreeModel来操作节点(节点修改后实时更新显示);

        之前做了个基于ImageIO的Java小工具,集合了图层合并切片分割等功能的小工具。这段时间无聊想整个文件拖拽,类似可编辑图层的升级版本小工具,考虑了许久就盯上了JTree的相关信息。

         对于以上内容介绍还有问题的可以留言交流,或者跳转到本项目的源码仓库GitHub直接体验用法。

        完整代码同步更新在GitHub仓库,想看可以点击下面链接跳转阅读。

项目地址:GitHub - neverever1533/EvolutionVector: 一些个人用的图形化小工具

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值