Java-swing树状图(JTree)

登录界面

 

主界面 

添加界面:

 

代码:

1、af-swing为自己定义的布局(封装了),下方提供下载链接.....

2、数据来源于place.txt,这个可以随意更改(一行代表一个数据)

3、用到的技术:JTree,背景图片的绘制,文件的读取以及自定义解析

4、功能,左上角当前用户的显示,左下角当前时间的显示及实时更新,添加功能,查询功能,城市信息的显示功能,数据来源文件的更换,以及菜单栏的小功能

由于是小作业,所以功能比较简单,后续如果需要,添加很方便

上核心代码:

package my;

import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class App
{
	private static void createGUI()
	{
		JFrame frame = new LoginFrame();
		frame.setVisible(true);		
	}
	
	public static void main(String[] args)
	{
		// 设置界面样式 Look And Feel
		try {
			UIManager.setLookAndFeel(
					UIManager.getSystemLookAndFeelClassName());
	    } catch(Exception ex)
		{
	    	ex.printStackTrace();
		}
		
		// 创建GUI线程
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				createGUI();
			}
		});
	}
}

 主面板

package my;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.SimpleDateFormat;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

import af.swing.AfEditText;
import af.swing.AfToaster;

public class MainFrame extends JFrame
{
	//用户信息
	public String user;
	public String password;
	public AfEditText textfield=new AfEditText();
	public JLabel disPlay=new JLabel("**:**:** --:--:--");
	public JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
	public String fileName;
	
	//注:import javax.swing.Timer;
	public Timer timer;
	
	public MainFrame(String title)
	{
		super(title);
		JsFrame jPanel = new JsFrame("地质图");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(750, 780);
		// 居中显示
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
		int x = ( screenSize.width - this.getWidth())/2;
		int y = ( screenSize.height - this.getHeight())/2;
		this.setLocation(x,  y);

		//内容面板
		JPanel root=new JPanel();
		this.setContentPane(root);
		root.setLayout(new BorderLayout());
		ImageIcon icon=new ImageIcon("hongqi.jpg"); //图片和项目同一路径,故不用图片的路径
		this.setIconImage(icon.getImage());
		

		//数据库
		root.add(textfield, BorderLayout.BEFORE_FIRST_LINE);
		textfield.setPlaceHolder("当前数据来源 : " + "place.txt");
		
		disPlay.setFont(new Font("宋体",Font.PLAIN,15));
		disPlay.setHorizontalAlignment(SwingConstants.CENTER);
		disPlay.setOpaque(true);
		//disPlay.setBackground(Color.DARK_GRAY);
		//disPlay.setForeground(Color.DARK_GRAY);
		
		//树状图
		JPanel sPanel = new JPanel();
		JScrollPane scrollPane = new JScrollPane(jPanel.tree);
		scrollPane.setPreferredSize(new Dimension(180, 300));
		sPanel.setLayout(new BorderLayout());
		sPanel.add(scrollPane, BorderLayout.WEST);    //树状图
		sPanel.add(jPanel.testButton, BorderLayout.PAGE_START);  //添加按钮
		sPanel.add(jPanel.findText, BorderLayout.PAGE_END);   //查询区域
		sPanel.add(jPanel.panel, BorderLayout.CENTER);   //显示区域
		root.add(sPanel, BorderLayout.CENTER);
		
		//状态栏
	    statusBar.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY),
	            new EmptyBorder(4, 4, 4, 4)));
	    statusBar.add(new JLabel("当前时间 : "));    
	    statusBar.add(disPlay);
	    root.add(statusBar, BorderLayout.SOUTH);
		
		//添加菜单
		JMenuBar menubar=new JMenuBar();
		this.setJMenuBar(menubar);
		
		//菜单01:文件
		JMenu fileMenu=new JMenu("文件");
		menubar.add(fileMenu);
		
		//菜单项
		JMenuItem fileOpenCmd=new JMenuItem("打开");
		JMenuItem fileSaveCmd=new JMenuItem("保存");
		JMenuItem fileSaveAsCmd=new JMenuItem("另存为...");
		JMenuItem fileReLoginCmd=new JMenuItem("重新登录");
		JMenuItem fileExitCmd=new JMenuItem("退出");
		
		//添加至菜单01:文件
		fileMenu.add(fileOpenCmd);
		fileMenu.add(fileSaveCmd);
		fileMenu.add(fileSaveAsCmd);
		fileMenu.addSeparator();
		fileMenu.add(fileReLoginCmd);
		fileMenu.add(fileExitCmd);
		
		//菜单02:帮助
		JMenu helpMenu=new JMenu("帮助");
		menubar.add(helpMenu);
		
		//菜单项
		JMenuItem helpAbout=new JMenuItem("关于");
		JMenuItem helpOpen=new JMenuItem("打开帮助");
		
		//添加至菜单02:帮助
		helpMenu.add(helpAbout);
		helpMenu.add(helpOpen);
		
		
		
		//添加“退出”菜单项  事件
		fileExitCmd.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				System.exit(0);
			}
	
		});
		fileOpenCmd.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				// TODO Auto-generated method stub
				test();
			}
	
		});
		fileReLoginCmd.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				// TODO Auto-generated method stub
				onLogin();
			}
	
		});
	}
	//选择打开文件
	private void test()
	{
		//创建一个文件选择器
		JFileChooser chooser=new JFileChooser();
		
		//FileNameExtensionFilter:文件名后缀过滤器
		FileNameExtensionFilter filter=new FileNameExtensionFilter("TXT文件", "txt");
		chooser.setFileFilter(filter);
		
		//显示对话框
		int ret=chooser.showOpenDialog(this);
		//获取用户选择的结果
		if(ret==JFileChooser.APPROVE_OPTION)
		{
			//结果为:已经存在的一个文件
			File file=chooser.getSelectedFile();
			fileName = file.getName();
			//数据库

			textfield.setPlaceHolder("当前数据来源 : " + fileName);
		}
	}

	
	//开始按钮
	public void onStart()
	{
		if(timer!=null)return;
		
		//创建定时器,每隔1000毫秒执行一次(更新一次)
		ActionListener task=new UpdateTask();
		timer=new Timer(1000,task);
		timer.start();
		
	}

	// 点'重新登录'
	private void onLogin()
	{
		
		MainFrame.this.setVisible(false);
		
		// 打开主界面
		LoginFrame loginFrame = new LoginFrame();
		loginFrame.setVisible(true);
	}
	
	//事件处理
	private class UpdateTask implements ActionListener
	{

		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			//1、actionPerformed()在界面工作线程里运行,所以必须迅速返回
			//2、在这里可以直接更新UI
			SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");
			String text=sdf.format(System.currentTimeMillis());
			disPlay.setText(text);
		}
		
	}

}

添加功能:

package jsUtil;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Rectangle;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;

import af.swing.AfPanel;
import af.swing.layout.AfColumnLayout;
import af.swing.layout.AfRowLayout;
import af.swing.AfEditText;


public class AddActionDialog extends JDialog
{
	public AfEditText shengField=new AfEditText();
	public AfEditText shiField=new AfEditText();
	public AfEditText xianField=new AfEditText();
	public JButton button=new JButton("确定");
	
	
	public AddActionDialog(JFrame owner)
	{
		super(owner,"添加",true);
		this.setSize(300,250);
		
		//设置一个容器
		AfPanel root=new AfPanel();
		this.setContentPane(root);
		root.setLayout(new AfColumnLayout(10));
		root.padding(10);
		
		
		
		//中间面板
		AfPanel mainPanel=new AfPanel();
		root.add(mainPanel, "1w"); //占据中间区域
		mainPanel.setLayout(new AfColumnLayout(10));
		
		mainPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
		mainPanel.padding(10);
		
		mainPanel.add(new JLabel("请输入"),"20px");
		mainPanel.add(shengField,"20px");
		mainPanel.add(shiField,"20px");
		mainPanel.add(xianField,"20px");
		mainPanel.setBackground(new Color(200, 236, 204,100));
		
		//提示
		shengField.setPlaceHolder("省(可省略不写)");
		shiField.setPlaceHolder("市(直辖市)");
		xianField.setPlaceHolder("县/区(可省略不写)");
		
		//底下
		AfPanel buttonPanel=new AfPanel();
		root.add(buttonPanel, "30px");//底部区域30px
		buttonPanel.setLayout(new AfRowLayout(10));
		buttonPanel.add(new JLabel(), "1w");//占位
		buttonPanel.add(button, "auto");

		//点击按钮时,关闭对话框
		button.addActionListener((e)->{
			setVisible(false);
		});
		
	}
	
	//显示对话框,并且待对话框关闭,返回用户输入的结果
	public String exec()
	{
		Rectangle frmRect=this.getOwner().getBounds();
		int width=this.getWidth();
		int height=this.getHeight();
		int x=frmRect.x+(frmRect.width-width)/2;
		int y = frmRect.y + (frmRect.height - height)/2;
		this.setBounds(x,y, width, height);
		
		this.setVisible(true);
		
		//返回输入
		if(xianField.getText().length() == 0 && shiField.getText().length() == 0 && shengField.getText().length() != 0)
			return shengField.getText().trim();
		else
		if(xianField.getText().length() == 0 && shiField.getText().length() != 0 && shengField.getText().length() != 0)
			return shengField.getText().trim() + "-" + shiField.getText().trim();
		else
		if(xianField.getText().length() != 0 && shiField.getText().length() != 0 && shengField.getText().length() != 0)
			return shengField.getText().trim() + "-" + shiField.getText().trim() + "-" + xianField.getText().trim();
		else
		if(xianField.getText().length() != 0 && shiField.getText().length() != 0 && shengField.getText().length() == 0)
			return shiField.getText().trim() + "-" + xianField.getText().trim();
		
		return shiField.getText().trim();
	}

}

自定义解析:

package jsUtil;

public class ParseStr
{
	//解析'-'的数量
	public static int sum(String lineTxt, int flag)
	{
    	for(int i=0;i<lineTxt.length();i++)
    	{
    		char c = lineTxt.charAt(i);
    		if(c == '-')
    		flag ++;
    	}
    	return flag;
	}
	//解析字符串,解析出 : 省-市-县
    public static String[] SubStr(String s, int f)
    {
    	String[] strPlace = new String[f+1];
    	if(f == 0)
    	{
    		strPlace[0] = s;
    	}
    	else
		if(f == 1)
		{
			String s1 = s.substring(0, s.indexOf("-") );
			String s2 = s.substring(s.indexOf("-")+1, s.length());
			strPlace[0] = s1;
			strPlace[1] = s2;
		}
		else
		if(f == 2)
		{
			int d1 = s.indexOf("-");
			int d2 = s.lastIndexOf("-");
			String s1 = s.substring(0, d1);
			String s2 = s.substring(d1+1, d2);
			String s3 = s.substring(d2+1, s.length());
			strPlace[0] = s1;
			strPlace[1] = s2;
			strPlace[2] = s3;
		}
		for(int i=0;i<strPlace.length;i++)
		{
			//System.out.print(strPlace[i] +"****");
		}
		//System.out.println();
    	return strPlace;	
    }
    
    //解析字符串,解析出 : [省, 市, 县] -> 省-市-县
    public static String SubStr2(String s2)
    {
    	String s = s2.substring(1, s2.length()-1).replace(", ", "-").trim();
    	return s;
    }
}

主面板的中间面板:

package my;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.WindowConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import af.swing.AfEditText;
import jsUtil.AddActionDialog;
import jsUtil.BgPicture;
import jsUtil.FileUlits;
import jsUtil.ParseStr;
import jsUtil.Query;

public class JsFrame extends JFrame
{
	public static JTree tree = null;
	public AfEditText findText = new AfEditText();
	public static JScrollPane scrollPane = new JScrollPane(tree);
	public static JButton testButton=new JButton("添加");
	BgPicture panel = new BgPicture();
	JLabel label = new JLabel("中国", JLabel.CENTER);
    // 创建树根节点
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("中国");
    
	public JsFrame(String title)
	{
		super(title);
		
		JPanel root = new JPanel();
		this.setContentPane(root);
		this.setSize(550, 400);
		root.setLayout(new BorderLayout());
		ImageIcon icon=new ImageIcon("hongqi.jpg"); //图片和项目同一路径,故不用图片的路径
		this.setIconImage(icon.getImage());
		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		
		// 居中显示
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
		int x = ( screenSize.width - this.getWidth())/2;
		int y = ( screenSize.height - this.getHeight())/2;
		this.setLocation(x,  y);
		
		//显示区域
		
		panel.setLayout(new BorderLayout());
		
		label.setFont(new Font("华文新魏", Font.BOLD, 30));
		panel.add(label, BorderLayout.CENTER);
		root.add(panel, BorderLayout.CENTER);

        /* 读取数据 */
        try 
        {
        	//从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。 
            BufferedReader br = new BufferedReader(new InputStreamReader
            				   (new FileInputStream(new File("place.txt")), "UTF-8"));

            String lineTxt = null; //代表读取一行数据
            lineTxt = br.readLine();
            while ((lineTxt = br.readLine()) != null) //逐行读取
            {
            	lineTxt = lineTxt.trim();
            	System.out.println(lineTxt);  //读取的一行数据

            	int flag = ParseStr.sum(lineTxt, 0);
            	//if(flag == 0)continue;
            	String[] strPlace = new String[flag+1];  //存地址place
            	strPlace = ParseStr.SubStr(lineTxt, flag); //解析地址
            	CreateTree(strPlace, rootNode);  //创建tree
	
            	}       
            br.close();
        } 
        catch (Exception e) 
        {
            System.err.println("read errors :" + e);
        }
        // 使用根节点创建树组件
        tree = new JTree(rootNode);
        tree.setRootVisible(false);

        // 设置树显示根节点句柄
        tree.setShowsRootHandles(true);

        scrollPane.setPreferredSize(new Dimension(150, 300));
        
        // 添加滚动面板到那内容面板
        root.add(scrollPane, BorderLayout.WEST);
		//向根面板添加一个按钮
		
		findText.setPlaceHolder("输入查询城市(回车执行)");
		root.add(testButton, BorderLayout.PAGE_START);
		root.add(findText, BorderLayout.PAGE_END);
		
		findText.addActionListener(new java.awt.event.ActionListener() 
		{
	        public void actionPerformed(ActionEvent e) 
	        {
	          Query.findInTree(tree, findText.getText());
	        }
	      });
        
        // 设置节点选中监听器
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent e) {
                System.out.println("当前被选中的节点: " + e.getPath());
                String s = e.getPath().toString();
                String str = ParseStr.SubStr2(s);
                label.setText(str);
            }
        });

		
		//添加监听器
		testButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) 
			{
				String str=getUserInput();
				System.out.println(str);
				int flag = ParseStr.sum(str, 0);
            	String[] strPlace = new String[flag+1];  //存地址place
            	strPlace = ParseStr.SubStr(str, flag); //解析地址
            	CreateTree(strPlace, rootNode);  //创建tree
            	try
				{
					FileUlits.write2Txt(str);
				} catch (Exception e1)
				{
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				System.out.println(str + "添加成功");

			}
			
		});
	
	}
	
	public String getUserInput()
	{
		AddActionDialog dialog=new AddActionDialog(this);
		return dialog.exec();
	}

    //树状图的数据
    private static void CreateTree(String[] strPlace, DefaultMutableTreeNode rootNode)
    {
		DefaultMutableTreeNode onNode;  //1节点
		DefaultMutableTreeNode twNode;  //2节点
		DefaultMutableTreeNode thNode;  //3节点
		if(strPlace.length == 1)
		{
			//二级节点
			onNode = new DefaultMutableTreeNode(strPlace[0]);
			DefaultMutableTreeNode node = Query.queryByTreeNode(rootNode, onNode.getUserObject());
			//System.out.println(node + "88888");
			if(node == null)
				rootNode.add(onNode);
			
		}
		else
		if(strPlace.length == 2)
		{
			//三级节点
			onNode = new DefaultMutableTreeNode(strPlace[0]);
			twNode = new DefaultMutableTreeNode(strPlace[1]);
			DefaultMutableTreeNode node1 = Query.queryByTreeNode(rootNode, onNode.getUserObject());
			if(node1 != null)
			{
				DefaultMutableTreeNode node2 = Query.queryByTreeNode(rootNode, twNode.getUserObject());
				if(node2 == null)
					node1.add(twNode);
			}
			else
			{
				rootNode.add(onNode);
				onNode.add(twNode);
			}

		}
		else
		if(strPlace.length == 3)  //河南省-南阳市-方城县||河南省-南阳市-唐河县
		{
    		//四级节点
			onNode = new DefaultMutableTreeNode(strPlace[0]);
			twNode = new DefaultMutableTreeNode(strPlace[1]);
    		thNode = new DefaultMutableTreeNode(strPlace[2]);
    		DefaultMutableTreeNode node1 = Query.queryByTreeNode(rootNode, onNode.getUserObject());
    		if(node1 != null)
    		{
    			DefaultMutableTreeNode node2 = Query.queryByTreeNode(rootNode, twNode.getUserObject());
    			{
    				if(node2 != null)
    				{
    					DefaultMutableTreeNode node3 = Query.queryByTreeNode(rootNode, thNode.getUserObject());
    					if(node3 == null)
    						node2.add(thNode);
    				}
    				else
    				{
    					node1.add(twNode);
    					twNode.add(thNode);
    				}
    			}
    		}
    		else
    		{
    			rootNode.add(onNode);
    			onNode.add(twNode);
    			twNode.add(thNode);
    		}
		}
    }	
}

需要的,下载链接在此:

中国省市县结构图

发布了246 篇原创文章 · 获赞 22 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/gjs935219/article/details/103345706
今日推荐