1. 程式人生 > >仿QQ聊天軟體及原始碼java版

仿QQ聊天軟體及原始碼java版

一直以來,很多java的同志們都沒有一個完整資料來參考。把原始碼貼出來,大家共享!

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Scanner;
import java.util.Stack;
import java.util.prefs.Preferences;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;


public class EQ extends JDialog{
	private JTextField ipEndTField;
	private JTextField ipStartTField;
	private JTextField userNameTField;//使用者框
	private JPasswordField passwordTField;//密碼框
	private JTextField placardPathTField;//placard:公告
	private JTextField updatePathTField;//更新路徑
	private JTextField pubPathTField;
	public static EQ frame = null;
	private ChatTree chatTree;
	private JPopupMenu popupMenu;//右鍵選單
	private JTabbedPane tabbedPane;//分頁面板
	private JToggleButton searchUserButton;//搜尋使用者按鈕
	private JProgressBar progressBar;//滾動條
	private JList faceList;
	private JButton selectInterfaceOKButton;
	private DatagramSocket ss;//資料報插座
	private final JLabel stateLabel;
	private static String user_dir;
	private static File localFile;
	private static File netFile;
	private String netFilePath;
	private JButton messageAlertButton;
	private Stack<String> messageStack;////Stack 類表示後進先出(LIFO)的物件堆疊。
	private ImageIcon messageAlertIcon;
	private ImageIcon messageAlertNullIcon;
	private Rectangle location;
	public static TrayIcon trayicon;
	private Dao dao;
	//Preferences.systeRoot:返回系統的根首選項節點   Preferences:引數選擇
	public final static Preferences preferences = Preferences.systemRoot();
	private JButton userInfoButton;
	//----------------------------------------------------------------------------------
	public static void main(String[] args){
		try{
			String laf = preferences.get("lookAndFeel", "java預設");
			if(laf.indexOf("當前系統") > -1){
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			}
			EQ frame = new EQ();
			frame.setVisible(true);
			frame.SystemTrayInitial();// 初始化系統欄
			frame.server();
			frame.checkPlacard();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	//----------------------------------------------------------------------------------
	public EQ(){
		super(new JFrame());
		frame = this;
		dao = Dao.getDao();
		location = dao.getLocation();
		setTitle("EQ聊天");
		setBounds(location);
		progressBar = new JProgressBar();
		//BevelBorder:該類實現簡單的雙線斜面邊框。Bevel:斜面     lowered:凹入斜面型別。
		progressBar.setBorder(new BevelBorder(BevelBorder.LOWERED));
		tabbedPane = new JTabbedPane();
		popupMenu = new JPopupMenu();
		chatTree = new ChatTree(this);
		user_dir = System.getProperty("user.dir");// 程式執行路徑用於系統更新
		localFile = new File(user_dir + File.separator + "EQ.jar");// 本地EQ檔案
		stateLabel = new JLabel();// 狀態列標籤
		this.addWindowListener(new FrameWindowListener());// 新增窗體監視器
		this.addComponentListener(new ComponentAdapter(){
			public void componentResized(final ComponentEvent e){
				saveLocation();
			}
			public void componentMoved(final ComponentEvent e){
				saveLocation();
			}
		});
		try{// 啟動通訊服務埠
			ss = new DatagramSocket(1111);
		}catch(SocketException e2){
			if(e2.getMessage().startsWith("Address already in use")){
				showMessageDialog("服務埠被佔用,或者本軟體已經執行。");
			}
			System.exit(0);
		}
		{// 初始化公共資訊按鈕
			messageAlertIcon = new ImageIcon(EQ.class.getResource("/image/messageAlert.gif"));
			messageAlertNullIcon = new ImageIcon(EQ.class.getResource("/image/messageAlertNull20.gif"));
			messageStack = new Stack<String>();
			messageAlertButton = new JButton();
			messageAlertButton.setHorizontalAlignment(SwingConstants.RIGHT);
			messageAlertButton.setContentAreaFilled(false);//不填充內容區域
			final JPanel BannerPanel = new JPanel();
			BannerPanel.setLayout(new BorderLayout());
			this.add(BannerPanel,BorderLayout.NORTH);
			userInfoButton = new JButton();
			BannerPanel.add(userInfoButton,BorderLayout.WEST);
			userInfoButton.setMargin(new Insets(0,0,0,10));//Margin:邊距    insets:插入 
			initUserInfoButton();// 初始化本地使用者頭像按鈕
			BannerPanel.add(messageAlertButton,BorderLayout.CENTER);
			messageAlertButton.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if(!messageStack.empty()){
						showMessageDialog(messageStack.pop());//堆疊頂部的物件(Vector 物件中的最後一項)。 
					}
				}
			});
			messageAlertButton.setIcon(messageAlertIcon);
			showMessageBar();
		}
		this.add(tabbedPane,BorderLayout.CENTER);
		tabbedPane.setTabPlacement(SwingConstants.LEFT);//設定此選項卡窗格的選項卡布局
		ImageIcon userTicon = new ImageIcon(EQ.class.getResource("/image/tabIcon/tabLeft.PNG"));
		tabbedPane.addTab(null,userTicon,createUserList(),"使用者列表");
		ImageIcon sysOTicon = new ImageIcon(EQ.class.getResource("/image/tabIcon/tabLeft2.PNG"));
		tabbedPane.addTab(null, sysOTicon, createSysToolPanel(), "系統操作");
		ImageIcon sysSTicon = new ImageIcon(EQ.class.getResource("/image/tabIcon/tabLeft3.png"));
		tabbedPane.addTab(null, sysSTicon, createSysSetPanel(), "系統設定");
		this.setAlwaysOnTop(true);//總在頂部
	}
	//----------------------------------------------------------------------------------
	private JScrollPane createSysSetPanel(){//系統設定面板
		final JPanel sysSetPanel = new JPanel();
		JScrollPane scrollPane = new JScrollPane(sysSetPanel);
		sysSetPanel.setLayout(new BoxLayout(sysSetPanel,BoxLayout.Y_AXIS));
		scrollPane.setBorder(new EmptyBorder(0,0,0,0));
		final JPanel sysPathPanel = new JPanel();
		sysPathPanel.setMaximumSize(new Dimension(600,200));
		sysPathPanel.setBorder(new TitledBorder("系統路徑"));//title - 邊框應顯示的標題
		sysPathPanel.setLayout(new GridLayout(0,1));
		sysSetPanel.add(sysPathPanel);
		sysPathPanel.add(new JLabel("程序升級路徑"));
		updatePathTField = new JTextField(preferences.get("updatePath", "請輸入路徑"));
		sysPathPanel.add(updatePathTField);
		sysPathPanel.add(new JLabel("系統公告路徑:"));
		placardPathTField = new JTextField(preferences.get("placardPath","請輸入路徑"));
		sysPathPanel.add(placardPathTField);
		sysPathPanel.add(new JLabel("公共程式路徑:"));
		pubPathTField = new JTextField(preferences.get("pubPath", "請輸入路徑"));
		sysPathPanel.add(pubPathTField);
		final JButton pathOKButton = new JButton("確定");
		pathOKButton.setActionCommand("sysOK");
		pathOKButton.addActionListener(new SysSetPanelOKListener());
		sysSetPanel.add(pathOKButton);
		final JPanel loginPanel = new JPanel();
		loginPanel.setMaximumSize(new Dimension(600, 90));
		loginPanel.setBorder(new TitledBorder("登入升級伺服器"));
		final GridLayout gridLayout_1 = new GridLayout(0, 1);
		gridLayout_1.setVgap(5);
		loginPanel.setLayout(gridLayout_1);
		sysSetPanel.add(loginPanel);
		final JPanel panel_7 = new JPanel();
		panel_7.setLayout(new BoxLayout(panel_7, BoxLayout.X_AXIS));
		loginPanel.add(panel_7);
		panel_7.add(new JLabel("使用者名稱:"));
		userNameTField = new JTextField(preferences.get("username", "請輸入使用者名稱"));
		panel_7.add(userNameTField);
		final JPanel panel_8 = new JPanel();
		panel_8.setLayout(new BoxLayout(panel_8, BoxLayout.X_AXIS));
		loginPanel.add(panel_8);
		panel_8.add(new JLabel("密 碼:"));
		passwordTField = new JPasswordField("*****");
		panel_8.add(passwordTField);
		final JButton loginOKButton = new JButton("確定");
		sysSetPanel.add(loginOKButton);
		loginOKButton.setActionCommand("loginOK");
		loginOKButton.addActionListener(new SysSetPanelOKListener());
		final JPanel ipPanel = new JPanel();
		final GridLayout gridLayout_2 = new GridLayout(0, 1);
		gridLayout_2.setVgap(5);
		ipPanel.setLayout(gridLayout_2);
		ipPanel.setMaximumSize(new Dimension(600, 90));
		ipPanel.setBorder(new TitledBorder("IP搜尋範圍"));
		sysSetPanel.add(ipPanel);
		final JPanel panel_5 = new JPanel();
		panel_5.setLayout(new BoxLayout(panel_5, BoxLayout.X_AXIS));
		ipPanel.add(panel_5);
		panel_5.add(new JLabel("起始IP:"));
		ipStartTField = new JTextField(preferences.get("ipStart", "192.168.0.1"));
		panel_5.add(ipStartTField);
		final JPanel panel_6 = new JPanel();
		panel_6.setLayout(new BoxLayout(panel_6, BoxLayout.X_AXIS));
		ipPanel.add(panel_6);
		panel_6.add(new JLabel("終止IP:"));
		ipEndTField = new JTextField(preferences.get("ipEnd", "192.168.1.255"));
		panel_6.add(ipEndTField);
		final JButton ipOKButton = new JButton("確定");
		ipOKButton.setActionCommand("ipOK");
		ipOKButton.addActionListener(new SysSetPanelOKListener());
		sysSetPanel.add(ipOKButton);
		return scrollPane;
	}
	//----------------------------------------------------------------------------------
	private JScrollPane createUserList(){// 使用者列表面板
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		addUserPopup(chatTree,getPopupMenu());// 為使用者新增彈出選單
		scrollPane.setViewportView(chatTree);
		scrollPane.setBorder(new EmptyBorder(0,0,0,0));
		chatTree.addMouseListener(new ChatTreeMouseListener());
		
		return scrollPane;
	}
	//----------------------------------------------------------------------------------
	private JScrollPane createSysToolPanel() {// 系統工具面板
		JPanel sysToolPanel = new JPanel(); // 系統工具面板
		sysToolPanel.setLayout(new BorderLayout());
		JScrollPane sysToolScrollPanel = new JScrollPane();
		sysToolScrollPanel
				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		sysToolScrollPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
		sysToolScrollPanel.setViewportView(sysToolPanel);
		sysToolPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
		JPanel interfacePanel = new JPanel();
		sysToolPanel.add(interfacePanel, BorderLayout.NORTH);
		interfacePanel.setLayout(new BorderLayout());
		interfacePanel.setBorder(new TitledBorder("介面選擇-再次啟動生效"));
		faceList = new JList(new String[]{"當前系統", "java預設"});
		interfacePanel.add(faceList);
		faceList.setBorder(new BevelBorder(BevelBorder.LOWERED));
		final JPanel interfaceSubPanel = new JPanel();
		interfaceSubPanel.setLayout(new FlowLayout());
		interfacePanel.add(interfaceSubPanel, BorderLayout.SOUTH);
		selectInterfaceOKButton = new JButton("確定");
		selectInterfaceOKButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				preferences.put("lookAndFeel", faceList.getSelectedValue().toString());
				JOptionPane.showMessageDialog(EQ.this, "重新執行本軟體後生效");
			}
		});
		interfaceSubPanel.add(selectInterfaceOKButton);

		JPanel searchUserPanel = new JPanel(); // 使用者搜尋面板
		sysToolPanel.add(searchUserPanel);
		searchUserPanel.setLayout(new BorderLayout());
		final JPanel searchControlPanel = new JPanel();
		searchControlPanel.setLayout(new GridLayout(0, 1));
		searchUserPanel.add(searchControlPanel, BorderLayout.SOUTH);
		final JList searchUserList = new JList(new String[]{"檢測使用者列表"});// 新新增使用者列表
		final JScrollPane scrollPane_2 = new JScrollPane(searchUserList);
		scrollPane_2.setDoubleBuffered(true);
		searchUserPanel.add(scrollPane_2);
		searchUserList.setBorder(new BevelBorder(BevelBorder.LOWERED));
		searchUserButton = new JToggleButton();
		searchUserButton.setText("搜尋新使用者");
		searchUserButton.addActionListener(new SearchUserActionListener(searchUserList));
		searchControlPanel.add(progressBar);
		searchControlPanel.add(searchUserButton);
		searchUserPanel.setBorder(new TitledBorder("搜尋使用者"));

		final JPanel sysUpdatePanel = new JPanel();
		sysUpdatePanel.setOpaque(false);
		sysUpdatePanel.setLayout(new GridBagLayout());
		sysUpdatePanel.setBorder(new TitledBorder("系統操作"));
		sysToolPanel.add(sysUpdatePanel, BorderLayout.SOUTH);
		final JButton sysUpdateButton = new JButton("系統更新");
		final GridBagConstraints gridBagConstraints_1 = new GridBagConstraints();
		gridBagConstraints_1.gridx = 0;
		gridBagConstraints_1.gridy = 0;
		sysUpdatePanel.add(sysUpdateButton, gridBagConstraints_1);
		sysUpdateButton.addActionListener(new SysUpdateListener());// 新增系統更新事件
		final JLabel updateLabel = new JLabel("最近更新:");
		final GridBagConstraints updateLabelLayout = new GridBagConstraints();
		updateLabelLayout.gridy = 1;
		updateLabelLayout.gridx = 0;
		sysUpdatePanel.add(updateLabel, updateLabelLayout);
		final JLabel updateDateLabel = new JLabel();// 程式更新日期標籤
		Date date = new Date(localFile.lastModified());
		String dateStr = String.format("%tF %<tr", date);
		updateDateLabel.setText(dateStr);
		final GridBagConstraints updateDateLayout = new GridBagConstraints();
		updateDateLayout.gridy = 2;
		updateDateLayout.gridx = 0;
		sysUpdatePanel.add(updateDateLabel, updateDateLayout);
		final JLabel updateStaticLabel = new JLabel("更新狀態:");
		final GridBagConstraints updateStaticLayout = new GridBagConstraints();
		updateStaticLayout.gridy = 3;
		updateStaticLayout.gridx = 0;
		sysUpdatePanel.add(updateStaticLabel, updateStaticLayout);
		final JLabel updateInfoLabel = new JLabel();// 版本資訊標籤
		checkSysInfo(updateInfoLabel);// 呼叫檢測版本更新的方法
		final GridBagConstraints gridBagConstraints_5 = new GridBagConstraints();
		gridBagConstraints_5.gridy = 4;
		gridBagConstraints_5.gridx = 0;
		sysUpdatePanel.add(updateInfoLabel, gridBagConstraints_5);
		JPanel statePanel = new JPanel();
		add(statePanel, BorderLayout.SOUTH);
		statePanel.setLayout(new BorderLayout());
		statePanel.add(stateLabel);
		stateLabel.setText("總人數:" + chatTree.getRowCount());
		return sysToolScrollPanel;
	}
	//----------------------------------------------------------------------------------
	private void initUserInfoButton(){
		try{
			String ip = InetAddress.getLocalHost().getHostAddress();
			User user = dao.getUser(ip);
			userInfoButton.setIcon(user.getIconImg());
			userInfoButton.setText(user.getName());
			userInfoButton.setIconTextGap(JLabel.RIGHT);
			userInfoButton.setToolTipText(user.getTipText());
			userInfoButton.getParent().doLayout();
		}catch(UnknownHostException e1){
			e1.printStackTrace();
		}
	}
	//----------------------------------------------------------------------------------
	private void showMessageBar(){// 顯示公告資訊按鈕的執行緒
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					if (!messageStack.empty()) {
						try {
							messageAlertButton.setIcon(messageAlertNullIcon);
							messageAlertButton.setPreferredSize(new Dimension(20, 20));
							Thread.sleep(500);
							messageAlertButton.setIcon(messageAlertIcon);
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					} else {
						try {
							Thread.sleep(3000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}).start();
	}
	//----------------------------------------------------------------------------------
	private void checkSysInfo(final JLabel updateInfo){
		new Thread(new Runnable(){
			public void run(){
				String info = "";
				while(true){
					try{
						netFilePath = preferences.get("updatePath", "EQ.jar");
						if(netFilePath.equals("EQ.jar")){
							info = "<html><center><font color=red><b>無法登入</b><br>未設定升級路徑</font></center></html>";
							updateInfo.setText(info);
							continue;
						}
						netFile = new File(netFilePath);
						if(netFile.exists()){
							Date netDate = new Date(netFile.lastModified());
							if(!localFile.exists()){
								info = "<html><font color=blue>本地程式位置出錯!</font></html>";
							}else{
								Date localDate = new Date(localFile.lastModified());
								if(netDate.after(localDate)){
									info = "<html><font color=blue>網路上有最新程式!</font></html>";
									pushMessage(info);
								}else{
									info = "<html><font color=green>現在是最新程式!</font></html>";
								}
							}
						}else{
							info = "<html><center><font color=red><b>無法訪問</b><br>升級路徑</font></center></html>";
						}
						updateInfo.setText(info);
						Thread.sleep(5*1000);
					}catch(InterruptedException e){
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	//----------------------------------------------------------------------------------
	class SearchUserActionListener implements ActionListener{
		private final JList list;
		SearchUserActionListener(JList list){
			this.list = list;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(searchUserButton.isSelected()){
				searchUserButton.setText("停止搜尋");
				new Thread(new Runnable(){
					public void run(){
						Resource.searchUsers(chatTree, progressBar,list, searchUserButton);
					}
				}).start();
			}else{
				searchUserButton.setText("搜尋新使用者");
			}
			
		}
	}
	//----------------------------------------------------------------------------------
	class SysSetPanelOKListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String command = e.getActionCommand();
			if(command.equals("sysOK")){
				String updatePath = updatePathTField.getText();
				String placardPath = placardPathTField.getText();
				String pubPath = pubPathTField.getText();
				preferences.put("updatePath", updatePath); // 設定系統升級路徑
				preferences.put("placardPath", placardPath);// 設定系統公告路徑
				preferences.put("pubPath", pubPath); // 設定公共程式路徑
				JOptionPane.showMessageDialog(EQ.this, "系統設定儲存完畢");
			}
			if (command.equals("loginOK")) {
				String username = userNameTField.getText();
				String password = new String(passwordTField.getPassword());
				preferences.put("username", username); // 設定系統升級路徑
				preferences.put("password", password);// 設定系統公告路徑
				JOptionPane.showMessageDialog(EQ.this, "登入設定儲存完畢");
			}
			if (command.equals("ipOK")) {
				String ipStart = ipStartTField.getText();
				String ipEnd = ipEndTField.getText();
				try {
					InetAddress.getByName(ipStart);
					InetAddress.getByName(ipEnd);
				} catch (UnknownHostException e1) {
					JOptionPane.showMessageDialog(EQ.this, "IP地址格式錯誤");
					return;
				}
				preferences.put("ipStart", ipStart); // 設定系統升級路徑
				preferences.put("ipEnd", ipEnd);// 設定系統公告路徑
				JOptionPane.showMessageDialog(EQ.this, "IP設定儲存完畢");
			}
		}
	}
	//----------------------------------------------------------------------------------
	private final class SysUpdateListener implements ActionListener{// 系統更新事件

		@Override
		public void actionPerformed(final ActionEvent e) {
			// TODO Auto-generated method stub
			String username = preferences.get("username", null);
			String password = preferences.get("password", null);
			if(username == null || password == null){
				pushMessage("未設定登入升級伺服器的使用者名稱或密碼");
				return;
			}
			Resource.loginPublic(username, password);
			updateProject();
		}
	}
	//----------------------------------------------------------------------------------
	private class ChatTreeMouseListener extends MouseAdapter{// 使用者列表的監聽器
		public void mouseClicked(final MouseEvent e){
			if (e.getClickCount() == 2) {
				TreePath path = chatTree.getSelectionPath();
				if (path == null)
					return;
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
						.getLastPathComponent();
				User user = (User) node.getUserObject();
				try {
					TelFrame.getInstance(ss, new DatagramPacket(new byte[0], 0,
							InetAddress.getByName(user.getIp()), 1111),
							chatTree);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	//----------------------------------------------------------------------------------
	private void server(){// 伺服器啟動方法
		new Thread(new Runnable(){
			public void run(){
				while(true){
					if(ss != null){
						byte[] buf = new byte[4096];
						DatagramPacket dp = new DatagramPacket(buf,buf.length);
						try{
							ss.receive(dp);
						}catch(IOException e){
							e.printStackTrace();
						}
						TelFrame.getInstance(ss,dp,chatTree);
					}
				}
			}
		}).start();
	}
	//----------------------------------------------------------------------------------
	private void addUserPopup(Component component, final JPopupMenu popup){// 新增使用者彈出選單
		component.addMouseListener(new MouseAdapter(){
			public void mousePressed(MouseEvent e){
				if(e.isPopupTrigger()){
					showMenu(e);
				}
			}
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger())
					showMenu(e);
			}
			private void showMenu(MouseEvent e){
				if(chatTree.getSelectionPaths() == null){
					popupMenu.getComponent(0).setEnabled(false);
					popupMenu.getComponent(2).setEnabled(false);
					popupMenu.getComponent(3).setEnabled(false);
					popupMenu.getComponent(4).setEnabled(false);
					popupMenu.getComponent(5).setEnabled(false);
				}else{
					if(chatTree.getSelectionPaths().length < 2){
						popupMenu.getComponent(3).setEnabled(false);
					}else {
						popupMenu.getComponent(3).setEnabled(true);
					}
					popupMenu.getComponent(0).setEnabled(true);
					popupMenu.getComponent(2).setEnabled(true);
					popupMenu.getComponent(4).setEnabled(true);
					popupMenu.getComponent(5).setEnabled(true);
				}
				popup.show(e.getComponent(), e.getX(), e.getY());
			}
		});
	}
	//----------------------------------------------------------------------------------
	private void saveLocation(){// 儲存主窗體位置的方法
		location = getBounds();
		dao.updateLocation(location);
	}
	//----------------------------------------------------------------------------------
	protected JPopupMenu getPopupMenu(){// 建立使用者彈出選單
		if (popupMenu == null) {
			popupMenu = new JPopupMenu();
			popupMenu.setOpaque(false);
		}
		final JMenuItem rename = new JMenuItem();
		popupMenu.add(rename);
		rename.addActionListener(new RenameActionListener());
		rename.setText("更名");
		final JMenuItem addUser = new JMenuItem();
		addUser.addActionListener(new AddUserActionListener());
		popupMenu.add(addUser);
		addUser.setText("新增使用者");
		final JMenuItem delUser = new JMenuItem();
		delUser.addActionListener(new delUserActionListener());
		popupMenu.add(delUser);
		delUser.setText("刪除使用者");
		final JMenuItem messagerGroupSend = new JMenuItem();
		messagerGroupSend
				.addActionListener(new messagerGroupSendActionListener());
		messagerGroupSend.setText("信使群發");
		popupMenu.add(messagerGroupSend);
		final JMenuItem accessComputerFolder = new JMenuItem("訪問主機資源");
		accessComputerFolder.setActionCommand("computer");
		popupMenu.add(accessComputerFolder);
		accessComputerFolder
				.addActionListener(new accessFolderActionListener());
		final JMenuItem accessPublicFolder = new JMenuItem();
		popupMenu.add(accessPublicFolder);
		accessPublicFolder.setOpaque(false);
		accessPublicFolder.setText("訪問公共程式");
		accessPublicFolder.setActionCommand("public");
		accessPublicFolder.addActionListener(new accessFolderActionListener());
		return popupMenu;
	}
	//----------------------------------------------------------------------------------
	private void updateProject(){// 程式更新方法
		netFilePath = preferences.get("updatePath", "EQ.jar");
		if(netFilePath.equals("EQ.jar")){
			pushMessage("未設定升級路徑");
			return;
		}
		netFile = new File(netFilePath);
		localFile = new File(user_dir + File.separator + "EQ.jar");
		if (localFile != null && netFile != null && netFile.exists()
				&& localFile.exists()) {
			Date netDate = new Date(netFile.lastModified());
			Date localDate = new Date(localFile.lastModified());
			if (netDate.after(localDate)) {
				new Thread(new Runnable() {
					public void run() {
						try {
							Dialog frameUpdate = new UpdateFrame();
							frameUpdate.setVisible(true);
							Thread.sleep(2000);
							FileInputStream fis = new FileInputStream(netFile);
							FileOutputStream fout = new FileOutputStream(
									localFile);
							int len = fis.available();
							if (len > 0) {
								byte[] data = new byte[len];
								if (fis.read(data) > 0) {
									fout.write(data);
								}
							}
							fis.close();
							fout.close();
							frameUpdate.setVisible(false);
							frameUpdate = null;
							showMessageDialog("更新完畢,請重新啟動程式。");
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}).start();
			} else {
				showMessageDialog("已經是最新的程式了。");
			}
		}
	}
	//----------------------------------------------------------------------------------
	private void checkPlacard() { // 檢測公告資訊方法
		String placardDir = preferences.get("placardPath", null);
		if (placardDir == null) {
			pushMessage("未設定公告路徑");
			return;
		}
		File placard = new File(placardDir);
		try {
			if (placard.exists() && placard.isFile()) {
				StringBuilder placardStr = new StringBuilder();
				Scanner sc = new Scanner(new FileInputStream(placard));
				while (sc.hasNextLine()) {
					placardStr.append(sc.nextLine());
				}
				pushMessage(placardStr.toString());
			}
		} catch (FileNotFoundException e) {
			pushMessage("公告路徑錯誤,或公告檔案不存在");
		}
	}
	//----------------------------------------------------------------------------------
	public void setStatic(String str){// 設定狀態列資訊
		if(stateLabel != null){
			stateLabel.setText(str);
		}
	}
	
	public void pushMessage(String info){// 堆壓資訊
		if(!messageStack.contains(info)){
			messageStack.push(info);
		}
	}
	
	private void showMessageDialog(String message){
		JOptionPane.showMessageDialog(this, message);
	}
	//----------------------------------------------------------------------------------
	private String showInputDialog(String str){// 顯示輸入對話方塊
		String newName = JOptionPane.showInputDialog(this,
				"<html>輸入<font color=red>" + str + "</font>的新名字</html>");
		return newName;
	}
	private class accessFolderActionListener implements ActionListener {// 訪問資源
		public void actionPerformed(final ActionEvent e) {
			TreePath path = chatTree.getSelectionPath();
			if (path == null)
				return;
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
					.getLastPathComponent();
			User user = (User) node.getUserObject();
			String ip = "\\\\"+user.getIp();
			String command = e.getActionCommand();
			if (command.equals("computer")) {
				Resource.startFolder(ip);
			}
			if (command.equals("public")) {
				String serverPaeh = preferences.get("pubPath", null);
				if (serverPaeh == null) {
					pushMessage("未設定公共程式路徑");
					return;
				}
				Resource.startFolder(serverPaeh);
			}
		}
	}

	private class RenameActionListener implements ActionListener {// 更名
		public void actionPerformed(final ActionEvent e) {
			TreePath path = chatTree.getSelectionPath();
			if (path == null)
				return;
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
					.getLastPathComponent();
			User user = (User) node.getUserObject();
			String newName = showInputDialog(user.getName());
			if (newName != null && !newName.isEmpty()) {
				user.setName(newName);
				dao.updateUser(user);
				DefaultTreeModel model = (DefaultTreeModel) chatTree.getModel();
				model.reload();
				chatTree.setSelectionPath(path);
				initUserInfoButton();
			}
		}
	}
	private class FrameWindowListener extends WindowAdapter {
		public void windowClosing(final WindowEvent e) {// 系統關閉事件
			setVisible(false);
		}
	}
	private class AddUserActionListener implements ActionListener {
		public void actionPerformed(final ActionEvent e) {// 新增使用者
			String ip = JOptionPane.showInputDialog(EQ.this, "輸入新使用者IP地址");
			if (ip != null)
				chatTree.addUser(ip, "add");
		}
	}
	private class delUserActionListener implements ActionListener {
		public void actionPerformed(final ActionEvent e) {// 刪除使用者
			chatTree.delUser();
		}
	}
	private class messagerGroupSendActionListener implements ActionListener {// 信使群發
		public void actionPerformed(final ActionEvent e) {
			String message = JOptionPane.showInputDialog(EQ.this, "請輸入群發信息",
					"信使群發", JOptionPane.INFORMATION_MESSAGE);
			if (message != null && !message.equals("")) {
				TreePath[] selectionPaths = chatTree.getSelectionPaths();
				Resource.sendGroupMessenger(selectionPaths, message);
			} else if (message != null && message.isEmpty()) {
				JOptionPane.showMessageDialog(EQ.this, "不能傳送空資訊!");
			}
		}
	}
	private void SystemTrayInitial() { // 系統欄初始化
		if (!SystemTray.isSupported()) // 判斷當前系統是否支援系統欄
			return;
		try {
			String title = "TT";
			String company = "成都市同道科技有限公司";
			SystemTray sysTray = SystemTray.getSystemTray();
			Image image = Toolkit.getDefaultToolkit().getImage(
					EQ.class.getResource("/icons/sysTray.png"));// 系統欄圖示
			trayicon = new TrayIcon(image, title + "\n" + company, createMenu());
			trayicon.setImageAutoSize(true);
			trayicon.addActionListener(new SysTrayActionListener());
			sysTray.add(trayicon);
			trayicon.displayMessage(title, company, MessageType.INFO);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private PopupMenu createMenu() { // 建立系統欄選單的方法
		PopupMenu menu = new PopupMenu();
		MenuItem exitItem = new MenuItem("退出");
		exitItem.addActionListener(new ActionListener() { // 系統欄退出事件
					public void actionPerformed(ActionEvent e) {
						System.exit(0);
					}
				});
		MenuItem openItem = new MenuItem("開啟");
		openItem.addActionListener(new ActionListener() {// 系統欄開啟選單項事件
					public void actionPerformed(ActionEvent e) {
						if (!isVisible()) {
							setVisible(true);
							toFront();
						} else
							toFront();
					}
				});

		// 系統欄的訪問伺服器選單項事件
		MenuItem publicItem = new MenuItem("訪問伺服器");
		publicItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String serverPaeh = preferences.get("pubPath", null);
				if (serverPaeh == null) {
					pushMessage("未設定公共程式路徑");
					return;
				}
				Resource.startFolder(serverPaeh);
			}
		});
		menu.add(publicItem);
		menu.add(openItem);
		menu.addSeparator();
		menu.add(exitItem);
		return menu;
	}
	class SysTrayActionListener implements ActionListener {// 系統欄雙擊事件
		public void actionPerformed(ActionEvent e) {
			setVisible(true);
			toFront();
		}
	}
}


相關推薦

仿QQ聊天軟體原始碼java

一直以來,很多java的同志們都沒有一個完整資料來參考。把原始碼貼出來,大家共享! import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dialog; import java.a

仿QQ聊天軟體2.0

仿QQ聊天軟體2.0版 轉載請標明出處:牟尼的專欄 http://blog.csdn.net/u012027907     上次課設做了Java版的仿QQ聊天程式。這次軟體實訓,我們繼續完好了仿QQ聊天程式,將上次未完畢及不完好的地方

仿QQ聊天軟體java實現(一)

之前學java通訊的時候寫過簡單的通訊程式,但比較簡陋,於是重新寫了一個仿照QQ的聊天軟體,主要在介面上做了優化,增加了一些功能。實現的功能有註冊、登入、好友列表、分組、黑名單、新增好友、群列表、建立群、新增群、聊天氣泡、傳送文字、圖片、檔案、表情。 好了先上圖看下效果:

仿QQ聊天軟件2.0

字段 col 12px ava 字體設置 pic 清華大學 環境 總結 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/u012027907/article/details/369528

網路程式設計(三)---- MFC 仿QQ聊天軟體

今天來八一八,MFC的SOCKET 程式設計,利用CSocket實現一個基於TCP實現一個QQ聊天程式。你會發現,MFC要比WIN32 簡單的多。但是如果你不理解具體API socket基礎知識,你可能會覺得有一點費解。 所以在開始之前 我還是請大家先看看http://bl

JAVA仿QQ聊天系統4.0(擴充套件韓順平的程式的功能介面)附原始碼

 下載連結  http://download.csdn.net/detail/qq245034548/8391381連結:https://pan.baidu.com/s/1btDApLQuHvLk44EtWKQygw 密碼:3ezf4 詳細設計4.1 系統程式流程如下    

[原始碼和報告分享]基於java仿QQ聊天工具

概要設計 在客戶端:當用戶登入後,生成唯一的socket, 存放在Client實體類中,在整個客戶端就一個Client類和一個socket。有一個視窗控制器——ChatUIList,用來記錄使用者和好友聊天框是否開啟,當收到訊息後,首先在ChatUIList中查詢是否有好友的視窗,如果沒有則新建聊天框彈出並

仿QQ聊天程式(java

仿QQ聊天程式 一、設計內容及要求 1.1綜述 A.系統概述 我們要做的就是類似QQ這樣的面向企業內部的聊天軟體,基本功能和QQ類似。首先,系統分為兩大部分,第一部分是客戶端,是使用者使用的部分,第二部分就是伺服器,所有的客戶端都是通過伺服器來進行使用者身份驗證

JAVA 仿QQ聊天程式

一、設計內容及要求 1.1綜述 A.系統概述 我們要做的就是類似QQ這樣的面向企業內部的聊天軟體,基本功能和QQ類似。首先,系統分為兩大部分,第一部分是客戶端,是使用者使用的部分,第二部分就是伺服器,所有的客戶端都是通過伺服器來進行使用者身份驗證及聊天

Socket實現仿QQ聊天(可部署於廣域網)附原始碼(2)-伺服器搭建

1.前言      這是本系列的第二篇文章,第一篇文章得到了很多朋友們的支援,在這裡表示非常的感謝。對於這一系列文章需要補充的是這只是一篇入門級別的Socket通訊文章,對於專業人員來說完全可以跳過。本文只介紹一些基本TCP通訊技術並使用該技術實現聊天功能。本篇文章實現聊

Java通訊-仿QQ聊天專案

前後歷時一個多月的Java實現聊天通訊專案-仿QQ聊天室基本告一段落,期間面對了很多問題,也有不同的解決方案,重寫了幾次核心程式碼,等等問題。現在在專案的結束之時,給自己做一個總結,算是一個回顧,算是一次提升,也是一次新的開始。 Github連結

仿QQ聊天工具(JAVA實現)專案總結

一、遇到的異常及解決辦法 1.        org.hibernate.HibernateException:Could not parse configuration: /hibernate.cfg.xml ..省略 Caused by: org.dom4j.Docu

Netty 仿QQ聊天室 (實戰二)

Netty 聊天器(百萬級流量實戰二):仿QQ客戶端 瘋狂創客圈 Java 分散式聊天室【 億級流量】實戰系列之15 【部落格園 總入口 】 原始碼IDEA工程獲取連結:Java 聊天室 實戰 原始碼 寫在前面 ​ 大家好,我是作者尼恩。 今天是百萬級流量 Netty 聊天器 打造的系列文章的第二篇,

GFF高仿QQ客戶端伺服器

一、GFF簡介 GFF是仿QQ介面,通訊基於SAEA.MessageSocket、SAEA.Http、SAEA.MVC實現包含客戶端和伺服器的程式,原始碼完全公開,專案原始碼地址:https://github.com/yswenli/GFF ,大家可以去我的github瞭解,歡迎follow,st

GFF高仿QQ客戶端服務器

col ide {0} sed ogr ini 交流 包含 tor 一、GFF簡介 GFF是仿QQ界面,通信基於SAEA.MessageSocket、SAEA.Http、SAEA.MVC實現包含客戶端和服務器的程序,源碼完全公開,項目源碼地址:https://github

iOS感測器集錦、飛機大戰、開發除錯工具、強制更新、Swift仿QQ空間頭部等原始碼

iOS精選原始碼 飛機大作戰 iOS優質部落格 Apple於北京時間9月17日晚在官網釋出了Xcode 10正式版,QiShare團隊成員於9月18日中午統一升級以對現有專案做適配。期間,作者發現某專案使用Xcode 10編譯

python 實戰之模仿開發QQ聊天軟體(三)TCP/IP伺服器與客戶端建設

無論是p2p還是c/s還是b/s,只要用到通訊,必然是要用到今天寫的這個。 TCP/IP是網路軟體最核心的部分,缺少這個你只能當做單機遊戲玩。 TCP/IP,只需要搞清楚udp和tcp這兩個就可以了。 兩者的區別在於 udp每次傳送資訊都需要傳送ip和埠號,可以比

Netty 仿QQ聊天室(實戰二)

Netty 聊天器(百萬級流量實戰二):仿QQ客戶端 瘋狂創客圈 Java 分散式聊天室【 億級流量】實戰系列之15 【部落格園 總入口 】 寫在前面 ​ 大家好,我是作者尼恩。 ​ 今天是百萬級流量 Netty 聊天器 打造的系列文章的第二篇, 設計一個

WPF仿QQ聊天框表情文字混排實現

二話不說。先上圖 圖中分別有檔案、文字+表情、純文字的展示,對於同一個list不同的展示形式,很明顯,應該用多個DataTemplate,那麼也就需要DataTemplateSelector了: class MessageDataTemplateSe

Android仿qq聊天記錄待定與刪除功能效果

模仿手機qq,歷史聊天記錄長按會彈出待定和刪除按鈕的效果。qq效果圖  程式碼實現的效果圖 首先,看到這個效果,想一下實現的思路:彈出的待辦和刪除按鈕,是通過dialog實現的。那麼這個dialog就要能完成幾個效果,第一:自定義介面,第二:控制dialog的顯示位置,第三