具体效果
效果如上图,左边边文件树用jtree,右边用jtextarea
操作
上图是具体操作,实现了左右边同时交互。
难点
是文件树的建立,及进入路径时文件树的强调
文件树建立
这种只能用子目录而不能用电脑根目录,原因是目录太多,启动时会很慢,需要延迟加载,这个需要在研究一下,我就没搞。
public static DefaultMutableTreeNode fileTree(File folder) {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(folder.getName());
if (folder.list() != null) {
for (String f : Objects.requireNonNull(folder.list())) {
File tmp_f = new File(folder + "\\" + f);
if (tmp_f.isFile()) {
// File的getName方法返回的是String,String有toString方法,所以可行,没有加上getName返回全路径,toSting和getName都能用
root.add(new DefaultMutableTreeNode(tmp_f.getName()));
} else if (tmp_f.isDirectory()) {
root.add(fileTree(tmp_f));
}
}
}
return root;
}
文件树强调
直接扩展jtree类
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.io.File;
import java.util.Objects;
public class FileTrees extends JTree {
// private DefaultMutableTreeNode root;
public FileTrees(DefaultMutableTreeNode node) {
super(node);
}
public void findInTree(String str) {
Object root = this.getModel().getRoot();
TreePath treePath = new TreePath(root);
treePath = findInPath(treePath, str);
if (treePath != null) {
this.setSelectionPath(treePath);
this.scrollPathToVisible(treePath);
}
}
public TreePath findInPath(TreePath treePath, String str) {
Object object = treePath.getLastPathComponent();
if (object == null) {
return null;
}
String value = object.toString();
if (str.equals(value)) {
return treePath;
} else {
TreeModel model = this.getModel();
int n = model.getChildCount(object);
for (int i = 0; i < n; i++) {
Object child = model.getChild(object, i);
TreePath path = treePath.pathByAddingChild(child);
path = findInPath(path, str);
if (path != null) {
return path;
}
}
return null;
}
}
}
右边textarea
开始不是用这种方法,是另外用一个数组,和最新jtextarea数组的长度选择获取每次的最后一行,不过那样太麻烦了,我的方法是将整个text按照换行换成数组,每次去最后一个数组就可以了,出错也很少。
jt.addKeyListener(new KeyListener() {
// private StringBuffer textBuffer = new StringBuffer();
// 获取键值
private int currentKeyCode = 0;
@Override
public void keyTyped(KeyEvent e) {
// 以'Enter'键结束命令输入
if (currentKeyCode == KeyEvent.VK_ENTER) {
String[] a = jt.getText().split("\\n+");
// String input = jt.getText().substring(textBuffer.length(), jt.getText().length() - 1);
// System.out.println("a" + jt.getText() +" b");
// System.out.println("aaa" + a[a.length - 1]);
String input = a[a.length - 1];
String[] arr = input.split("\\s+");
switch (arr[0]) {
// 进入路径
case "cd": {
File ff = new File(arr[1]);
dictionary.findInTree(ff.getName());
main_file = ff;
jt.append("--------------------------------------------------\n");
break;
}
// 显示目录文件
case "dir": {
File ParFile = main_file.getParentFile();
for (File i : Objects.requireNonNull(ParFile.listFiles())) {
jt.append(i.getAbsolutePath() + "\n");
}
jt.append("--------------------------------------------------\n");
break;
}
// 删除文件或文件夹
case "del": {
File ff = new File(arr[1]);
if (ff.delete()){
System.out.printf(ff.getAbsolutePath() + "删除成功\n");
jt.append("----------------------------------------------\n");
}
break;
}
// 复制
case "copy": {
jt.append(PreFIle.copyFolder(arr[1], arr[2]));
jt.append("---------------------------------------------------\n");
break;
}
// 查找
case "sear": {
jt.append(PreFIle.search(main_file, arr[1]));
jt.append("---------------------------------------------------\n");
break;
}
//打开文件
case "open": {
File ff = new File(arr[1]);
JFrame tab = new SwitchFile(ff);
tab.setSize(1080, 720);
tab.setVisible(true);
jt.append("----------------------------------------------------\n");
break;
}
}
jt.append(main_file.getAbsolutePath() + "\n");
// textBuffer.append(input);
// textBuffer.append("\n");
// jt.append(input);
// jt.append("\n");
// jt.append(main_file.getAbsolutePath() + " \n");
}
}
@Override
public void keyPressed(KeyEvent e) {
currentKeyCode = e.getKeyCode();
}
@Override
public void keyReleased(KeyEvent e) {
}
});
jtree双击和三击
private static FileTrees getFileTrees(DefaultMutableTreeNode root) {
FileTrees dictionary = new FileTrees(root);
dictionary.setPreferredSize(new Dimension(300, 1920));
dictionary.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 3) {
// 按照鼠标点击的坐标点获取路径
TreePath selPath = dictionary.getPathForLocation(e.getX(), e.getY());
if (selPath != null)// 谨防空指针异常!双击空白处是会这样
{
// 获取文件路径
File ff = new File(String.valueOf(GetPath(selPath)));
// 点击文件子节点显示父文件夹的所有文件,当成简易的点击文件弹出文件窗口
if (ff.isFile()) {
ff = new File(String.valueOf(ff.getParentFile()));
}
SwitchFile tab = new SwitchFile(ff);
tab.setSize(1080, 720);
// 当文件夹里面没文件,之后目录时不显示新文件窗口
for (File file : Objects.requireNonNull(ff.listFiles())) {
if (file.isDirectory()) {
continue;
}
tab.setVisible(true);
}
// main_file = new File(String.valueOf(GetPath(selPath)));
// jt.append(main_file.getAbsolutePath() + " \n");
// 输出路径看一下
// // 获取这个路径上的最后一个组件,也就是双击的地方
// DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent();
// System.out.println(node.toString());// 输出这个组件toString()的字符串看一下
}
// 点击次数为2时将主路径改为点击的树节点的路径
} else if (e.getClickCount() == 2) {
TreePath selPath = dictionary.getPathForLocation(e.getX(), e.getY());
if (selPath != null)// 谨防空指针异常!双击空白处是会这样
{
// 同次数为2的。
main_file = new File(String.valueOf(GetPath(selPath)));
// 右边文本栏也就是命令行栏显示路径
jt.append(main_file.getAbsolutePath());
jt.append("\n\n");
}
}
}
});
return dictionary;
}
这个是打开文件和显示路径的,switchfile是自己写的类,就是仿照idea那样的可以看多个文件
代码如下
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class SwitchFile extends JFrame {
static JTabbedPane tp;
private static int i = 0;
public SwitchFile(){
super();
}
public SwitchFile(File file) {
this.setSize(new Dimension(2560,1440));
tp = new JTabbedPane();
File[] fs = file.listFiles();
JPanel[] jp = new JPanel[0];
if (fs != null) {
jp = new JPanel[fs.length];
}
if (fs != null) {
for (File fi_tmp:fs){
if (fi_tmp.isFile()){
try(
FileReader fr = new FileReader(fi_tmp);
BufferedReader br = new BufferedReader(fr);
) {
jp[i] = new JPanel();
JTextArea ta = new JTextArea();
while (true) {
// 一次读一行
String line = br.readLine();
if (null == line) break;
// 后面要加换行符。不然文本域里面换不了行
ta.append(line + "\r\n");
}
text_panel(jp[i],ta,fi_tmp.getName());
} catch (IOException e) {
e.printStackTrace();
}
i ++;
}
}
}
i = 0;
this.setContentPane(tp);
}
public static void text_panel(JPanel jp,JTextArea ta,String na){
// 把JPanel设置为border样式就自动布满了。。我还在想怎么对不齐之类的
jp.setLayout(new BorderLayout());
ta.setLineWrap(true);
// 文本域加上滚动效果
JScrollPane sp = new JScrollPane(ta);
jp.setLocation(0,0);
jp.add(sp);
tp.add(jp);
tp.setTitleAt(i,na);
}
}
代码如果有需要我会上传
视频在这B站