上一次我们建立一个比较简单的资源管理器,这次我们说一下上面的资源管理器的问题,并且得尽量的贴近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)的更多相关文章

  1. Jtree (节点的渲染+资源管理器)

    我们的还是自定义的Jtree的类: package jtree.customNode; import java.io.File; import javax.swing.JTree; import ja ...

  2. JTree实现电脑资源管理器

    0.前言 最近老师布置了一项用Java写资源管理器的任务,一开始以为简单,但是实际操作起来,却发现网上的资源用起来相对生疏.在使用中,我也遇到了许多问题,虽然不能像其他博主一样,写的非常齐全,但我还是 ...

  3. 使用Windows Form 制作一个简易资源管理器

    自制一个简易资源管理器----TreeView控件 第一步.新建project,进行基本设置:(Set as StartUp Project:View/Toolbox/TreeView) 第二步.开始 ...

  4. HDFS分布式文件系统资源管理器开发总结

      HDFS,全称Hadoop分布式文件系统,作为Hadoop生态技术圈底层的关键技术之一,被设计成适合运行在通用硬件上的分布式文件系统.它和现有的分布式文件系统有很多共同点,但同时,它和其他的分布式 ...

  5. 初识IO流之小型资源管理器

    初次接触到IO流,根据书本上的知识,加上自己的摸索,发现了一些好玩的事情.(书本上的知识或多或少,有时候不足以解决我们的问题!这时候我们就应该自己去求解!!! 所以我们学习的时候要抱有探索的精神,求知 ...

  6. yarn资源管理器高可用性的实现

    资源管理器高可用性 . The ResourceManager (RM) is responsible for tracking the resources in a cluster, and sch ...

  7. windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤

    大家都知道,我们打开一堆文件夹的时候,是什么样子 “厚厚的一叠”图标堆叠在一起的,非常的不方便 那么,是不是可以像浏览器一样的tab页面展示呢? 答案是可以的 安装好就是这样子的 是不是方便漂亮了很多 ...

  8. winform:简单文件资源管理器

    今天全部学习内容的体现就是winform的资源管理器.这个资源管理器主要由一个textbox获取路径,然后在treeview那里通过递归的方式呈现目录树,当用户点击treeview的节点是,会触发Af ...

  9. Visual C# 2010 实现资源管理器

    演练:使用设计器创建带有 ListView 和 TreeView 控件的资源管理器样式的界面 Visual Studio 2010     其他版本     此主题尚未评级 - 评价此主题   Vis ...

随机推荐

  1. 型牌男装施春蕾:分拆让马云对淘宝定位更清晰--互联网 -- CCTIME飞象网

    型牌男装施春蕾:分拆让马云对淘宝定位更清晰--互联网 -- CCTIME飞象网 型牌男装施春蕾:分拆让马云对淘宝定位更清晰          2011年6月17日 13:16  CCTIME飞象网   ...

  2. 我所理解的设计模式(C++实现)——策略模式(Strategy Pattern)

    概述: 每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法. 而策略模式就是对算法进行包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理.策 ...

  3. java笔记3之赋值运算符

    赋值运算符:        基本的赋值运算符:=            把=右边的数据赋值给左边.          扩展的赋值运算符:+=,-=,*=,/=,%=            += 把左边 ...

  4. Python学习日志(六)

    字符串的方法及注释 字符串转义字符含义 字符串格式化符号含义 eg:'a'的ASCii码是97 格式化操作符辅助指令 format()字符串格式化方法 字符串的格式化是指统一字符串格式 format( ...

  5. (转)苹果iOS开发者账号过期临时解决方法

    苹果iOS开发者账号过期临时解决办法 苹果iOS开发者账号一年的费用是99美金,作者最近由于各种原因,导致renew没能在账号过期之前支付好,所以在账号过期等待renew的期间,试了试一些非正常手段, ...

  6. Nginx学习之六-nginx核心进程模型

    一.Nginx整体架构 正常执行中的nginx会有多个进程,最基本的有master process(监控进程,也叫做主进程)和woker process(工作进程),还可能有cache相关进程. 一个 ...

  7. LaTeX笔记

    1.上下标: $x^n$, $x^{123}$, $x_n$, $x_{123}$, $C_n^m$, $C_{100}^{50}$ $x^n$, $x^{123}$, $x_n$, $x_{123} ...

  8. mysql 建立加密连接

    加密连接可提高数据的安全性,但会降低性能.要进行加密连接,必须满足以下要求: user权限表里要有相关的SSL数据列.如果安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列 ...

  9. Dynamics CRM记录页面上隐藏子网格“+”标识

    前段时间微软发布了Dynamics 365,这是Dynamics产品的又一次大的变动,期待新的版本能够更好的满足客户的需求,同时提供更多的可定制化的内容. 近期做Dynamics CRM项目遇到很多审 ...

  10. 通过Url传多个参数方法

    MVC3通过URL传值,一般情况下都会遇到[从客户端(&)中检测到有潜在危险的 Request.Path 值]的问题 这个问题的解决方法,我的其他博文已经有了说明,这里给出连接[从客户端(&a ...