Jtree(节点的渲染+资源管理器)(2)
上一次我们建立一个比较简单的资源管理器,这次我们说一下上面的资源管理器的问题,并且得尽量的贴近windows的资源管理器。
这样一个简单的资源管理树就完成了,下面我们说说它的问题:
① 图片和外观和Windows有差距
这个我们可以通过设置L&F和通过前面写的Renderer那样设置新的图片解决,不是大问题.
② 文件夹里文件多时展开会很慢,会导致界面假死
这个我们可以自己写一个缓加载的TreeNode,让它继承于DefaultMutableTreeNode,在它里面定义加载标示,然后使用SwingWorker或者多线程方式使Tree平稳加载,虽然麻烦,但是也可以解决.
③ Tree点击假死时,用户会以为出现问题,胡乱点击会加载多个事件
这个问题其实是Swing事件机制的问题,其实是没办法解决的,因为总会存在耗时的操作的,不等待是不可能的.但我们可以做更好的用户体验来避免这个问题,这里我想到的解决办法是在Tree上绘制一层GlassPane,屏蔽所有事件,提示用户,等加载完成后,取消GlassPane界面.
④ 只有我的电脑的基本文件,没有网上邻居之类的
这个问题很难解决,涉及到网上邻居就存在网络的问题了,还需要网络连接和扫描,开始我的思路是使用Apache的commons-client做,后来发现有人给出了更好的办法,使用Java的JFileChooser类,Java已经实现了很多我们需要实现的.
⑤ 取得的资源管理树的子目录是乱序的
这个很好解决,使我们的TreeNode实现Comparable接口就可以了.
为了解决这五个问题我们做的改进版:
首先我们解决问题一,看看我们的代码:
节点的图片的样式问题我们可以设置Renderer,又因为这些图片可以在JFileChooser的UI中取得,我们先参照JFileChooser的UI做一个FileView类:
// ***********************
// * FileView operations *
// ***********************
protectedclass BasicFileView extends FileView {
复写它的方法:
@Override
public String getName(File f) {
// Note: Returns display name rather than file name
String fileName = null;
if (f != null) {
fileName = chooser.getFileSystemView().getSystemDisplayName(f);
}
return fileName;
}
这个是显示名字.
@Override
public String getDescription(File f) {
return f.getName();
}
这个是描述
@Override
public String getTypeDescription(File f) {
String type = chooser.getFileSystemView().getSystemTypeDescription(
f);
if (type == null) {
if (f.isDirectory()) {
type = directoryDescriptionText;
} else {
type = fileDescriptionText;
}
}
return type;
}
这个是文件类别
@Override
public Icon getIcon(File f) {
这个是图片表示.
这样我们构建这个FileView之后我们需要的图片和名字就都可以取得了.
然后是我们的Renderer了:
privateclass FileSystemTreeRenderer extends DefaultTreeCellRenderer {
复写它的方法,设置我们从FileView取得图片和名字:
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,boolean leaf, int row,
boolean hasFocus) {
setText(getFileView(chooser).getName(node.getFile()));
setIcon(getFileView(chooser).getIcon(node.getFile()));
然后设置到树上:
tree.setCellRenderer(new FileSystemTreeRenderer());
看看效果:
是不是和Windows的很接近了,设置L&F,如下图:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
然后解决问题二,我们不能用树的原始节点了,用我们自己构造的,继承于它:
publicabstractclass LazyMutableTreeNode extends DefaultMutableTreeNode {
增加一个属性:
/** is node load. */
privatebooleanloaded = false;
提供一个虚方法给子类实现:
protectedabstractvoid loadChildren();
然后是我们的实现:
privateclass FileTreeNode extends LazyMutableTreeNode {
复写它的方法,非load不允许加载:
@Override
publicboolean isLeaf() {
if (!isLoaded()) {
returnfalse;
} else {
returnsuper.isLeaf();
}
}
还有它的现实名字:
@Override
public String toString() {
returnchooser.getFileSystemView().getSystemDisplayName(
(File) getUserObject());
}
实现虚方法:
@Override
protectedvoid loadChildren() {
FileTreeNode[] nodes = getChildren();
for (int i = 0, c = nodes.length; i < c; i++) {
add(nodes[i]);
}
}
这样问题二就解决了,同时也可以在这里解决我们的问题五,使我们的TreeNode实现Comparable接口:
privateclass FileTreeNode extends LazyMutableTreeNode implements
Comparable<Object> {
然后实现方法:
@Override
publicint compareTo(Object o) {
if (!(o instanceof FileTreeNode)) {
return 1;
}
return getFile().compareTo(((FileTreeNode) o).getFile());
}
最后在我们使用时:
// sort directories, FileTreeNode implements Comparable
FileTreeNode[] result = (FileTreeNode[]) nodes
.toArray(new FileTreeNode[0]);
Arrays.sort(result);
nodes.add(new FileTreeNode(result[i]));
这样我们加入的节点文件夹就都是排序的了.
然后我们解决问题四,三比较麻烦留在最后:
构建这个组件时,我们先构建JFileChooser
JFileChooser chooser = new JFileChooser();
增加监听:
protectedvoid installListeners() {
tree.addTreeSelectionListener(new SelectionListener());
chooser.getActionMap().put("refreshTree", new UpdateAction());
chooser.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke("F5"), "refreshTree");
chooser.addPropertyChangeListener(new ChangeListener());
}
在监听中展开树时,使用JFileChooser的方法:
/**
* tree node select change.
*/
privateclass SelectionListener implements TreeSelectionListener {
@Override
publicvoid valueChanged(TreeSelectionEvent e) {
getApproveSelectionAction()
.setEnabled(tree.getSelectionCount() > 0);
setSelectedFiles();
// the current directory is the one currently selected
TreePath currentDirectoryPath = tree.getSelectionPath();
if (currentDirectoryPath != null) {
File currentDirectory = ((FileTreeNode) currentDirectoryPath
.getLastPathComponent()).getFile();
chooser.setCurrentDirectory(currentDirectory);
}
}
}
这样我们所有的目录结构就不需要自己去循环构建了,使用JFileChooser为我们提供好的就可以了,如下图,网上邻居也有了,问题四完成了:
最后我们来解决问题三,为什么会假死,是因为文件夹多或者网速慢导致的,解决办法当然是多线程,但是多线程在Swing里容易出现线程不安全,因为它不在ADT上,这里我们使用SwingWorker,监听树的展开事件:
tree.addTreeExpansionListener(new TreeExpansion());
处理它:
privateclass TreeExpansion implements TreeExpansionListener {
@Override
publicvoid treeCollapsed(TreeExpansionEvent event) {
}
@Override
publicvoid treeExpanded(TreeExpansionEvent event) {
// ensure children gets expanded later
if (event.getPath() != null) {
Object lastElement = event.getPath().getLastPathComponent();
if (lastElement instanceof FileTreeNode && useNodeQueue)
if (((FileTreeNode) lastElement).isLoaded()) {
慢主要是在这里的处理,我们把它放在SwingWorker里面:
new WorkerQueue(node, tree, glassPane).execute();
然后看这个类:
privatestaticfinalclass WorkerQueue extends
SwingWorker<Void, FileTreeNode> {
复写它的方法,处理我们的TreeNode添加事件:
@Override
protected Void doInBackground() throws Exception {
glassPanel.setVisible(true);
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
publish((FileTreeNode) e.nextElement());
}
returnnull;
}
@Override
protectedvoid process(List<FileTreeNode> chunks) {
for (FileTreeNode fileTreeNode : chunks) {
fileTreeNode.getChildCount();
}
}
@Override
protectedvoid done() {
glassPanel.setVisible(false);
tree.repaint();
}
然后是处理我们在展开节点时屏蔽所有的鼠标点击并给以用户提示,这里我们自己绘制一个Component,把它设置为GlassPane,屏蔽所有事件:
/**
*/
publicclass GlassPane extends JComponent {
屏蔽所有事件,只能获得焦点:
// blocks all user input
addMouseListener(new MouseAdapter() {
});
addMouseMotionListener(new MouseMotionAdapter() {
});
addKeyListener(new KeyAdapter() {
});
setFocusTraversalKeysEnabled(false);
addComponentListener(new ComponentAdapter() {
publicvoid componentShown(ComponentEvent evt) {
requestFocusInWindow();
}
});
然后是绘制:
@Override
protectedvoid paintComponent(Graphics g) {
先绘制整体背景:
// gets the current clipping area
Rectangle clip = g.getClipBounds();
// sets a 65% translucent composite
AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.65f);
Composite composite = g2.getComposite();
g2.setComposite(alpha);
// fills the background
g2.setColor(getBackground());
g2.fillRect(clip.x, clip.y, clip.width, clip.height);
g2.setComposite(composite);
然后绘制一张提示图片,本来想绘制一个滚动的等待图标的,实在是没心情写了,随便Google了张图片放上去了.
if (image == null) {
try {
image = ImageIO.read(getClass().getResource("wait2.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
g.drawImage(image, getWidth() / 2 - 40, getHeight() / 2
- 80, 120, 120, null);
通过设置画面的GlassPane就可以了
Component glassPane = new GlassPane();
frame.getRootPane().setGlassPane(glassPane);
------没有完成,后面还有。留个尾巴
Jtree(节点的渲染+资源管理器)(2)的更多相关文章
- Jtree (节点的渲染+资源管理器)
我们的还是自定义的Jtree的类: package jtree.customNode; import java.io.File; import javax.swing.JTree; import ja ...
- JTree实现电脑资源管理器
0.前言 最近老师布置了一项用Java写资源管理器的任务,一开始以为简单,但是实际操作起来,却发现网上的资源用起来相对生疏.在使用中,我也遇到了许多问题,虽然不能像其他博主一样,写的非常齐全,但我还是 ...
- 使用Windows Form 制作一个简易资源管理器
自制一个简易资源管理器----TreeView控件 第一步.新建project,进行基本设置:(Set as StartUp Project:View/Toolbox/TreeView) 第二步.开始 ...
- HDFS分布式文件系统资源管理器开发总结
HDFS,全称Hadoop分布式文件系统,作为Hadoop生态技术圈底层的关键技术之一,被设计成适合运行在通用硬件上的分布式文件系统.它和现有的分布式文件系统有很多共同点,但同时,它和其他的分布式 ...
- 初识IO流之小型资源管理器
初次接触到IO流,根据书本上的知识,加上自己的摸索,发现了一些好玩的事情.(书本上的知识或多或少,有时候不足以解决我们的问题!这时候我们就应该自己去求解!!! 所以我们学习的时候要抱有探索的精神,求知 ...
- yarn资源管理器高可用性的实现
资源管理器高可用性 . The ResourceManager (RM) is responsible for tracking the resources in a cluster, and sch ...
- windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤
大家都知道,我们打开一堆文件夹的时候,是什么样子 “厚厚的一叠”图标堆叠在一起的,非常的不方便 那么,是不是可以像浏览器一样的tab页面展示呢? 答案是可以的 安装好就是这样子的 是不是方便漂亮了很多 ...
- winform:简单文件资源管理器
今天全部学习内容的体现就是winform的资源管理器.这个资源管理器主要由一个textbox获取路径,然后在treeview那里通过递归的方式呈现目录树,当用户点击treeview的节点是,会触发Af ...
- Visual C# 2010 实现资源管理器
演练:使用设计器创建带有 ListView 和 TreeView 控件的资源管理器样式的界面 Visual Studio 2010 其他版本 此主题尚未评级 - 评价此主题 Vis ...
随机推荐
- hdu 4585 Shaolin(STL map)
Problem Description Shaolin temple is very famous for its Kongfu monks.A lot of young men go to Shao ...
- Jmeter接口测试-badboy录制脚本(二)
1.脚本录制,采用badboy进行录制,操作步骤很简单 2.badboy简介: Badboy是一款免费WEB自动化测试工具. 官方下载地址:http://www.badboy.com.au badbo ...
- 菜鸟玩云计算之十六:Ubuntu14.04上创建的虚拟机迁移到RHEL6.4
菜鸟玩云计算之十六:Ubuntu14.04上创建的RHEL6.4虚拟机迁移到RHEL6.4主机上 RHEL6.4 Server作为虚拟机的HOST,执行以下的命令检查配置和安装相关软件: # egre ...
- 分享一次在Windows Server2012 R2中安装SQL Server2008
入手一台Windows Server2012云服务器,搭建一下服务环境,选用SQL Server2008 直奔主题,下好安装镜像后,直接双击 选择运行程序而不获取帮助 如图: 进入安装中心后选择 安装 ...
- Web前端开发面试题赋答案
第一部分:用CSS实现布局 让我们一起来做一个页面 首先,我们需要一个布局. 请使用CSS控制3个div,实现如下图的布局. 第二部分:用javascript优化布局 由于我们的用户群喜欢放大看页面 ...
- C3P0连接池配置方式
c3p0的配置方式分为三种,分别是 1.setters一个个地设置各个配置项 2.类路径下提供一个c3p0.properties文件 3.类路径下提供一个c3p0-config.xml文件 1.set ...
- C#读取word模版并对指定域写入数据保存为新word
引用: using System;using System.Collections.Generic;using System.Aspose.Words;using System.Windows.For ...
- javascript 操作 css Rule
//add addCssRule('.bcd',{'color':'red','font-weight':'bold','font-size':'12px'},document.styleSheets ...
- poj3282
定义一个有4x+1组成的无限集合x>0&x∈Z 素数 x 不能有x = y*z,y,z都是素数 合数 x 有x = y*z y|z中某个数是素数 simi数,只能由两个素数构成. 打 ...
- 8 个实用的 Linux netcat 命令示例
Netcat 或者叫 nc 是 Linux 下的一个用于调试和检查网络工具包.可用于创建 TCP/IP 连接,最大的用途就是用来处理 TCP/UDP 套接字. 这里我们将通过一些实例来学习 netca ...