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);
    		}
		}
    }	
}

需要的,下載鏈接在此:

 

中國省市縣結構圖

發佈了228 篇原創文章 · 獲贊 20 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章