自己动手写一个java版QQ

基于java实现的仿qq即时通讯工具   数据库使用sql server
项目源码http://git.oschina.net/qrne0607/javaqq  

1. 包分类




ht_功能函数包
  • send发送qq信息
  • sendMsg消息类
ht.bean
  • 三个数据表对应的java bean (java bean不包含数据库操作,仅有成员属性和setget方法)
ht.cmd用到的命令字和常量
  • Cmd
ht.db数据库操作包
  • DBConn数据库连接
  • DBOper数据库操作
ht.ui与界面有关的包
  • ChatUI聊天框
  • FindUI查找好友框
  • Login登录框
  • Lookusers查看好友信息
  • MainUI主界面框
  • RegUsers注册界面



  1. 数据表结构


Account:



friend:




3.部分代码

Send.java

package ht_;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Send {

	public void send(SendMsg msg)
	{
		
		try
		{
			//字节数组输出流
			ByteArrayOutputStream bos=new  ByteArrayOutputStream();
			ObjectOutputStream oos=new ObjectOutputStream(bos);
			
			oos.writeObject(msg);	
					
			//最终
			byte[] b=bos.toByteArray();//把要发送的信息转换为字节数组
			//网络上发送任何东西都是发送字节数组
			
			DatagramSocket socket=new DatagramSocket();//UDP通信
			
			InetAddress add=InetAddress.getByName(msg.friendAccount.getIpAddr());
			int port=msg.friendAccount.getPort();
			DatagramPacket p=new DatagramPacket(b,0,b.length,add,port);
			
			//发送 
			socket.send(p);
			socket.close();
			

					
		}catch (Exception e)
		{
			e.printStackTrace();
		}
		
		
		
		
	}



}

sendMsg:消息类

package ht_;

import ht.bean.Account;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import javax.swing.text.StyledDocument;

public class SendMsg implements Serializable{

	public int Cmd;//命令字
	public Account selfAccount,friendAccount;//自己的信息,对方的信息
	public StyledDocument doc;
	public String sFileName;
	public byte[] b;

	
}

java bean,以Account为例

package ht.bean;

import java.io.Serializable;

//对应Account表,一个字段对应一个成员变量
public class Account implements Serializable{

	private int qqCode;
	private String nickName;
	private String pwd;
	private String ipAddr;
	private int port;
	private int age;
	private String sex;
	private String nation;
	private String star;
	private String face;
	private String remark;
	private String selfsign;
	private int status;//0离线 1在线 2隐身 3 忙碌
	private String groupname;
	
	
	public String getGroupname() {
		return groupname;
	}
	public void setGroupname(String groupname) {
		this.groupname = groupname;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
	public int getQqCode() {
		return qqCode;
	}
	public void setQqCode(int qqCode) {
		this.qqCode = qqCode;
	}
	public String getNickName() {
		return nickName;
	}
	public void setNickName(String nickName) {
		this.nickName = nickName;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public String getIpAddr() {
		return ipAddr;
	}
	public void setIpAddr(String ipAddr) {
		this.ipAddr = ipAddr;
	}
	public int getPort() {
		return port;
	}
	public void setPort(int port) {
		this.port = port;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getNation() {
		return nation;
	}
	public void setNation(String nation) {
		this.nation = nation;
	}
	public String getStar() {
		return star;
	}
	public void setStar(String star) {
		this.star = star;
	}
	public String getFace() {
		return face;
	}
	public void setFace(String face) {
		this.face = face;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
	public String getSelfsign() {
		return selfsign;
	}
	public void setSelfsign(String selfsign) {
		this.selfsign = selfsign;
	}
}

命令字和常量Cmd.java

package ht.cmd;
//系统中要用到的命令字,常量
public class Cmd {
	
	public static final int CMD_ONLINE=1000;//上线通知
	public static final int CMD_OFFLINE=1001;//下线通知
	public static final int CMD_BUSY=1002;//忙碌
	public static final int CMD_LEAVE=1003;//离开	
	
	public static final int CMD_CHAT=1004;//聊天
	public static final int CMD_DOUDONG=1005;//抖动
	public static final int CMD_ADDFRIEND=1006;//添加好友
	public static final int CMD_DELFRIEND=1007;//删除好友
	public static final int CMD_SENDFILE=1008;//发送文件	
	public static final int CMD_AFREEFRIEND=1009;//发送文件
	public static final int CMD_REJECTFRIEND=1010;//发送文件
	public static final int CMD_FILESUCC=1011;//文件发送成功
	public static final int CMD_FILEFAILED=1012;//拒绝接收文件
	public static final int CMD_FILESEND=1013;//文件发送
	

	public static final String F_FRIEND="好友";
	public static final String F_FAMILY="家人";
	public static final String F_CLASSMATE="同学";
	public static final String F_HMD="黑名单";
	
	
	
}
连接数据库:DBconn.java
package ht.db;

import java.sql.Connection;
import java.sql.DriverManager;


//这类仅仅负责调入驱动程序 并且连接数据库 其他功能都在库同名javaBean里写
public class DBConn {

//使用传统方法jdbcdriver连接数据库
//	static String url="jdbc:sqlserver://localhost:1433;databasename=QQ";//连接数据库的字符串  localhost可以写ip(一般服务器)或者机器名, 1433是数据库默认端口
//	static String driver="com.microsoft.sqlserver.jdbc.SQLServerDriver";//驱动程序;

//使用JDBC-ODBC桥连方式操作数据库
	static String url="jdbc:odbc:LocalServer";//连接数据源  数据源名称是LocalServer
	static String driver="sun.jdbc.odbc.JdbcOdbcDriver";//驱动程序;
	
	static Connection conn=null;
	
	
	
	//静态语句块 负责调入驱动 整个程序只需要调用一次
	static
	{

		try {
			
			Class.forName(driver);
			
		}catch(ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		

	}
	
	
	
	//构造函数 用来连接数据库
	public Connection DBConn()
	{
		
		try
		{
			//2.连接数据库
			conn=DriverManager.getConnection(url);
			
			System.out.println("数据库连接成功。。。");
			
		}catch(Exception e)
		{
			e.printStackTrace();						
		}
		
		
		return conn;
		
		
	}
	
}	
	
数据库操作:DBConn.java
package ht.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;

import ht.bean.Account;
import ht.cmd.Cmd;

//进行数据库操作的函数
public class DBOper {

	//所有值都放到account对象里去了 ,传一个Account对象过来,注册用户的函数
	public boolean addUser(Account acc)
	{
		boolean bok=false;
		Connection conn=new DBConn().DBConn();
		
		try {
			
			String sql="insert into account values(?,?,?,?,?,?,?,?,?,?,?,?,?)";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			int i=1;
			pstmt.setInt(i++,acc.getQqCode());
			pstmt.setString(i++,acc.getNickName());
			pstmt.setString(i++,acc.getPwd());
			pstmt.setString(i++,acc.getIpAddr());
			pstmt.setInt(i++,acc.getPort());
			pstmt.setInt(i++,acc.getAge());
			pstmt.setString(i++,acc.getSex());
			pstmt.setString(i++,acc.getNation());
			pstmt.setString(i++,acc.getStar());
			pstmt.setString(i++,acc.getFace());
			pstmt.setString(i++,acc.getRemark());
			pstmt.setString(i++,acc.getSelfsign());
			pstmt.setInt(i++,acc.getStatus());
			//执行数据库操作
	//		bok=pstmt.execute();
			if(pstmt.executeUpdate()>0)
			{
				bok=true;
			}
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		return bok;
		
	}
	//判断端口是否已经被占用
	public boolean isPort(int port)
	{
		
		boolean bok=false;
		
		Connection conn=new DBConn().DBConn();
		
		try {
			
			String sql="select port from account where port =?";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			
			pstmt.setInt(1,port);
			ResultSet rs=pstmt.executeQuery();
			if(rs.next())
			{
				bok=true;
			}
			
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		
		
		
		return bok;
		
		
	}
	
	//登录函数,返回account对象
	public Account login(Account acc)
	{
				
		Connection conn=new DBConn().DBConn();
		
		try {
			
			String sql="select * from account where qqCode =? and pwd=?";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			
			pstmt.setInt(1,acc.getQqCode());
			pstmt.setString(2,acc.getPwd());
			
			//ResultSet表示从数据库中查询到的返回结果
			ResultSet rs=pstmt.executeQuery();
			if(rs.next())//查到了账号名跟密码匹配的东西  已经登陆了
			{	//登陆成功,读取用户所有信息
				//修改状态为在线(1)
				acc.setNickName(rs.getString("nickname").trim());
				acc.setIpAddr(rs.getString("ipaddr").trim());
				acc.setPort(rs.getInt("port"));
				acc.setAge(rs.getInt("age"));
				acc.setSex(rs.getString("sex").trim());
				acc.setNation(rs.getString("nation").trim());
				acc.setStar(rs.getString("star").trim());
				acc.setFace(rs.getString("face").trim());
				acc.setRemark(rs.getString("remark").trim());
				acc.setSelfsign(rs.getString("selfsign").trim());
				
				acc.setStatus(1);//修改对象值为1
				//修改数据库中存储状态为上线
				modifyStatus(acc.getQqCode(),1);
				
			}
			
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		
		
		return acc;
		
		
	}
	
	
	//查找个人资料
		public Account findByQQcode (int qqcode)
		{
					
			Connection conn=new DBConn().DBConn();
			Account acc=new Account();
			
			
			try {
				
		
				String sql="select * from account where qqCode =?";
				PreparedStatement pstmt=conn.prepareStatement(sql);
				
				pstmt.setInt(1,qqcode);
			
				
				//ResultSet表示从数据库中查询到的返回结果
				ResultSet rs=pstmt.executeQuery();
				if(rs.next())//查到了账号名跟密码匹配的东西  已经登陆了
				{	//登陆成功,读取用户所有信息
		
					acc.setQqCode(rs.getInt("qqcode"));
					
					acc.setNickName(rs.getString("nickname").trim());
					acc.setIpAddr(rs.getString("ipaddr").trim());
					acc.setPort(rs.getInt("port"));
					acc.setAge(rs.getInt("age"));
					acc.setSex(rs.getString("sex").trim());
					acc.setNation(rs.getString("nation").trim());
					acc.setStar(rs.getString("star").trim());
					acc.setFace(rs.getString("face").trim());
					acc.setRemark(rs.getString("remark").trim());
					acc.setSelfsign(rs.getString("selfsign").trim());
					
				}
				
				
				pstmt.close();
				conn.close();
			}catch(Exception e)
			{
				e.printStackTrace();
				
			}
			
			
			
			return acc;
			
			
		}
	
	public boolean modifyStatus(int qqcode,int status)
	{
		boolean bok=false;
		Connection conn=new DBConn().DBConn();
		
		try {
			
			String sql="update account set status=? where qqcode=?";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			pstmt.setInt(1,status);
			pstmt.setInt(2,qqcode);
			
		
			if(pstmt.executeUpdate()>0)
			{
				bok=true;
			}
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		return bok;
		
	}
	
	
	//返回头像
	public String getFace(int qqcode)
	{
		String face="";
		Connection conn=new DBConn().DBConn();
		
		try {
			
			String sql="select face from account where qqCode =?";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			
			pstmt.setInt(1,qqcode);
			
			//ResultSet表示从数据库中查询到的返回结果
			ResultSet rs=pstmt.executeQuery();
			if(rs.next())//查到了账号名跟密码匹配的东西  已经登陆了
			{	
				face=rs.getString("face").trim();
				
				
			}
			
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		
		
		return face;
		
		
	}
	
	//返回所有好友,家人,同学,黑名单等资料
	public Vector<Account> getAllInfo(Account acc)
	{
				
		Connection conn=new DBConn().DBConn();
		Vector<Account> allInfo=new Vector<Account>();
		try {
			
			//取出朋友的信息,在线状态,以及分组
			String sql="select a.*,f.groupname from account a right outer join friend f on a.qqcode=f.friendaccount where f.selfAccount =?";
			PreparedStatement pstmt=conn.prepareStatement(sql);
			
			pstmt.setInt(1,acc.getQqCode());
			
			
			//ResultSet表示从数据库中查询到的返回结果
			ResultSet rs=pstmt.executeQuery();
			while(rs.next())//查到了账号名跟密码匹配的东西  已经登陆了
			{	
				Account a=new Account();//一条记录创建一个Account对象
				a.setQqCode(rs.getInt("qqcode"));
				a.setNickName(rs.getString("nickname").trim());
				a.setPwd(rs.getString("pwd").trim());		
				a.setIpAddr(rs.getString("ipaddr").trim());
				a.setPort(rs.getInt("port"));
				a.setAge(rs.getInt("age"));
				a.setSex(rs.getString("sex").trim());
				a.setNation(rs.getString("nation").trim());
				a.setStar(rs.getString("star").trim());
				a.setFace(rs.getString("face").trim());
				a.setRemark(rs.getString("remark").trim());
				a.setSelfsign(rs.getString("selfsign").trim());
				a.setStatus(rs.getInt("status"));
				a.setGroupname(rs.getString("groupname").trim());
				
				allInfo.add(a);
				
			}
			
			
			pstmt.close();
			conn.close();
		}catch(Exception e)
		{
			e.printStackTrace();
			
		}
		
		
		
		return allInfo;
		
		
	}
	
	//查找好友
		public Vector<Account> find(Account acc)
		{
					
			Connection conn=new DBConn().DBConn();
			Vector allInfo=new Vector();
			try {
				
				//取出朋友的信息,在线状态,以及分组
			//	String sql="select * from account where qqcode=? or nickname like ? or age=? or sex=? ";
				
				String sql="select * from account where qqcode=? or nickname =? or age=?";
				
				PreparedStatement pstmt=conn.prepareStatement(sql);
				
				int i=1;
				
				pstmt.setInt(i++,acc.getQqCode());
				pstmt.setString(i++,acc.getNickName());
				pstmt.setInt(i++,acc.getAge());
		//		pstmt.setString(i++,acc.getSex());
				
				//ResultSet表示从数据库中查询到的返回结果
				ResultSet rs=pstmt.executeQuery();
				while(rs.next())//查到了账号名跟密码匹配的东西  已经登陆了
				{	
					Vector a=new Vector();
					a.addElement(rs.getInt("qqcode"));
					a.addElement(rs.getString("nickname").trim());
			//		a.addElement(rs.getString("pwd").trim());		
					a.addElement(rs.getString("ipaddr").trim());
					a.addElement(rs.getInt("port"));
					a.addElement(rs.getInt("age"));
					a.addElement(rs.getString("sex").trim());
					a.addElement(rs.getString("nation").trim());
					a.addElement(rs.getString("star").trim());
					a.addElement(rs.getString("face").trim());
					a.addElement(rs.getString("remark").trim());
					a.addElement(rs.getString("selfsign").trim());
					a.addElement(rs.getInt("status"));
			//		a.addElement(rs.getString("groupname").trim());
					
					allInfo.add(a);
					
				}
				
				
				pstmt.close();
				conn.close();
			}catch(Exception e)
			{
				e.printStackTrace();
				
			}
			
			
			
			return allInfo;
			
			
		}
		//添加好友
		public boolean addFriend(Account acc,int friendcode)
		{
			
			
			
			boolean bok=false;
			Connection conn=new DBConn().DBConn();
			
			try {
				
				String sql="insert into friend values(?,?,?,?)";
				PreparedStatement pstmt=conn.prepareStatement(sql);
				int i=1;
				pstmt.setInt(i++,acc.getQqCode());
				pstmt.setInt(i++,friendcode);
				pstmt.setString(i++,Cmd.F_FRIEND);
				pstmt.setInt(i++,0);
				pstmt.executeUpdate();
				pstmt.close();
			//互相加好友	
				pstmt=conn.prepareStatement(sql);
				i=1;
				pstmt.setInt(i++,friendcode);
				pstmt.setInt(i++,acc.getQqCode());
				pstmt.setString(i++,Cmd.F_FRIEND);
				pstmt.setInt(i++,0);
				pstmt.executeUpdate();
				pstmt.close();
				
				
				conn.close();
			}catch(Exception e)
			{
				e.printStackTrace();
				
			}
			
			return true;
			
		}	
		
		//删除好友
		public boolean delFriend(Account acc,int friendcode)
		{
			
			Connection conn=new DBConn().DBConn();
			
			try {
				
				String sql="delete friend where selfAccount=? and friendAccount=?";
				PreparedStatement pstmt=conn.prepareStatement(sql);
				int i=1;
				pstmt.setInt(i++,acc.getQqCode());
				pstmt.setInt(i++,friendcode);
				pstmt.executeUpdate();
				pstmt.close();
			//互相删除好友	
				pstmt=conn.prepareStatement(sql);
				i=1;
				pstmt.setInt(i++,friendcode);
				pstmt.setInt(i++,acc.getQqCode());
				pstmt.executeUpdate();
				pstmt.close();
				
				
				conn.close();
			}catch(Exception e)
			{
				e.printStackTrace();
				
			}
			
			return true;
			
		}	
		
		//移动好友
				public boolean moveFriend(Account acc,int friendcode,String groupname)
				{
					
					Connection conn=new DBConn().DBConn();
					
					try {
						
						String sql="update friend set groupname=? where selfAccount=? and friendAccount=?";
						PreparedStatement pstmt=conn.prepareStatement(sql);
						int i=1;
						pstmt.setString(i++,groupname);
						pstmt.setInt(i++,acc.getQqCode());
						pstmt.setInt(i++,friendcode);
						pstmt.executeUpdate();
						
						
						pstmt.close();
						conn.close();
					}catch(Exception e)
					{
						e.printStackTrace();
						
					}
					
					return true;
					
				}			
		
		
}

UI:ChatUI.java
package ht.ui;

import ht.bean.Account;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;


import javax.swing.ButtonGroup;
import javax.swing.ComboBoxModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;




import ht.bean.Account;
import ht.cmd.Cmd;
import ht.db.DBOper;
import ht_.Send;
import ht_.SendMsg;


public class ChatUI extends JFrame implements ActionListener,ItemListener{

	private Account selfAccount,friendAccount;
	JTextPane recePanel,sendPanel;
	JButton btnSend,btnshake,btnsendFile,btnColor,btnClose;
	JComboBox cbFont,cbSize,cbImg;
	JLabel lblboy,lblgrid,lblfriendInfo;
	
	
	public ChatUI()
	{
		
	}
	public ChatUI(Account self,Account friend)
	{
		this.selfAccount=self;
		this.friendAccount=friend;
		ImageIcon ic=new ImageIcon(friend.getFace());
	
		setIconImage(ic.getImage());
		String str="";
		if(friend.getRemark()!=null && friend.getRemark().equals(""))
		{
			str=friend.getRemark()+"(";
			
		}
		else
		{
			str=friend.getNickName()+"(";
		
		}
		str+= friend.getQqCode()+")"+friend.getSelfsign();
		
		setTitle(str);
		lblfriendInfo=new JLabel(str,ic,JLabel.LEFT);

		add(lblfriendInfo,BorderLayout.NORTH);
		//中间放接受框
		recePanel=new JTextPane();
		recePanel.setEditable(false);
		
		//下边放一排按钮
		btnSend=new JButton("发送消息");
		btnshake=new JButton(new ImageIcon("images/dd.jpg"));
		btnshake.setMargin(new Insets(0,0,0,0));//调整按钮为图片大小
		btnsendFile=new JButton("发送文件");
		btnColor=new JButton("字体颜色");
		
		String fonts[]= {"宋体","楷体","黑体","隶书","微软雅黑"};
		cbFont=new JComboBox(fonts);
		String fontsize[] = {"10","12","14","16","18"};
		cbSize=new JComboBox(fontsize);
		cbImg=new JComboBox(getImg());
		cbImg.setPreferredSize(new Dimension(100, 28));
				
		JPanel btnPanel=new JPanel(new FlowLayout(FlowLayout.LEFT));
		btnPanel.add(cbFont);
		btnPanel.add(cbSize);
		btnPanel.add(btnColor);
		btnPanel.add(cbImg);
		btnPanel.add(btnshake);
		btnPanel.add(btnsendFile);
		
		sendPanel=new JTextPane();
		JPanel southPanel=new JPanel(new BorderLayout());
		southPanel.add(btnPanel,BorderLayout.NORTH);
		southPanel.add(new JScrollPane(sendPanel));

		JPanel centerPanel=new JPanel(new GridLayout(2,1,10,10));
		
		centerPanel.add(new JScrollPane(recePanel));
		centerPanel.add(new JScrollPane(southPanel));
		add(centerPanel);
		
	//	add(southPanel,BorderLayout.SOUTH);
		
		
		
		
		btnSend=new JButton("发送(S)");
		btnSend.setMnemonic('S');
		
		btnClose=new JButton("关闭(X)");
		btnClose.setMnemonic('X');
		
		JPanel bottomPanel=new JPanel(new FlowLayout(FlowLayout.RIGHT));
		
		bottomPanel.add(btnSend);
		bottomPanel.add(btnClose);
		
		add(bottomPanel,BorderLayout.SOUTH);
		
		lblboy=new JLabel(new ImageIcon("images/boy.jpg"));
		lblgrid=new JLabel(new ImageIcon("images/girl.jpg"));
		
		JPanel rightPanel=new JPanel(new GridLayout(2,1,5,0));
		
		rightPanel.add(lblboy);
		rightPanel.add(lblgrid);
		add(rightPanel,BorderLayout.EAST);
		
		btnSend.addActionListener(this);
		btnshake.addActionListener(this);
		btnsendFile.addActionListener(this);
		btnColor.addActionListener(this);
		btnClose.addActionListener(this);
		
		cbFont.addItemListener(this);
		cbSize.addItemListener(this);
		cbImg.addItemListener(this);
		
		
		
		setSize(670,550);
		setVisible(true);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		sendPanel.requestFocus(); 
		
		
	}
	private Icon[] getImg() {
		Icon[] icon=null;
		
		File file=new File("bq");
		String sfile[]=file.list();
		
		icon=new ImageIcon[sfile.length];
		for(int i=0;i<sfile.length;i++)
		{
			icon[i]=new ImageIcon("bq/"+sfile[i]);
		}
		
		
		
		
		return icon;
		
	}
	
	
	
	
	
	
	
	@Override
	public void itemStateChanged(ItemEvent e) {
		if(e.getSource()==cbFont || e.getSource()==cbSize)
		{
			
			String sfont=cbFont.getSelectedItem().toString();
			int size=Integer.parseInt(cbSize.getSelectedItem().toString());
			
			sendPanel.setFont(new Font(sfont,Font.PLAIN,size));
			
			
			
		}else if(e.getSource()==cbImg)
		{
			Icon g=(Icon)cbImg.getSelectedItem();
			sendPanel.insertIcon(g);
			
			
		}
		
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		
		if(e.getSource()==btnSend)
		{
			try {
				appendView(selfAccount.getNickName(),sendPanel.getStyledDocument());
				//生成发送类
				SendMsg msg=new SendMsg();
				msg.Cmd=Cmd.CMD_CHAT;
				msg.doc=sendPanel.getStyledDocument();//聊天内容 
				msg.selfAccount=selfAccount;
				msg.friendAccount=friendAccount;
				//发送
				new Send().send(msg);
				
				
				sendPanel.setText("");

			
			} catch (BadLocationException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			sendPanel.setText("");
		
		}else if(e.getSource()==btnshake)
		{
			SendMsg msg=new SendMsg();
			msg.Cmd=Cmd.CMD_DOUDONG;
			msg.selfAccount=selfAccount;
			msg.friendAccount=friendAccount;
			
			new Send().send(msg);

			shake();
			
		}
		else if(e.getSource()==btnsendFile)
		{//发送文件
			//创建文件选择框
			FileDialog fdlg=new FileDialog(this,"打开64k以下的文件",FileDialog.LOAD);
			
			fdlg.show();
			String sfilename=fdlg.getDirectory()+"\\"+fdlg.getFile();
			
			File file=new File(sfilename);//创建文件
			
			//UDP文件传输一次最多64k
			if(file.length()>1024*64)
			{
				JOptionPane.showMessageDialog(this, "文件不能大于64k");
				return;
				
			}
			
			try {
				
			byte[] b=new byte[(int)file.length()];
			FileInputStream fis=new FileInputStream(file);
			fis.read();//读取文件内容
			fis.close();
			
			SendMsg msg=new SendMsg();
			msg.Cmd=Cmd.CMD_FILESEND;
			msg.selfAccount=selfAccount;
			msg.friendAccount=friendAccount;
			msg.sFileName=fdlg.getFile();//文件名
			msg.b=b;
			new Send().send(msg);
			
			
			
			
			}catch(Exception e1)
			{
				e1.printStackTrace();
			}
			
			
		}
		else if(e.getSource()==btnColor)
		{
			JColorChooser cc=new JColorChooser();
			Color c=cc.showDialog(this, "选择字体颜色", Color.BLACK);
			sendPanel.setForeground(c);
		}
		else if(e.getSource()==btnClose)
		{
			dispose();
		}
	}
	
	public void shake()
	{

		Point p=this.getLocationOnScreen();
		for(int i=0;i<20;i++)
		{
			if(i%2==0)
			{
				setLocation(p.x+5,p.y+5);
			}else
			{
				setLocation(p.x-5,p.y-5);
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e1) {
				
				e1.printStackTrace();
			}
		}
		
		
		
	}
	
	//获取接受框内容
	public void appendView(String name, StyledDocument xx) throws BadLocationException{
		StyledDocument vdoc=recePanel.getStyledDocument();
		
		Date date=new Date();
		
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		
		String time=sdf.format(date);
		SimpleAttributeSet as=new SimpleAttributeSet();
		
		
		String s=name+"    "+time+"\n";
		
		vdoc.insertString(vdoc.getLength(),s,as);
		int end=0;
		while(end<xx.getLength())
		{
			Element e0=xx.getCharacterElement(end);
			
			SimpleAttributeSet asl=new SimpleAttributeSet();
			StyleConstants.setForeground(asl,StyleConstants.getForeground(e0.getAttributes()));
			StyleConstants.setFontSize(asl,StyleConstants.getFontSize(e0.getAttributes()));
			StyleConstants.setFontFamily(asl,StyleConstants.getFontFamily(e0.getAttributes()));
			
			s=e0.getDocument().getText(end, e0.getEndOffset()-end);
			
			if("icon".equals(e0.getName()))
			{
				vdoc.insertString(vdoc.getLength(),s,e0.getAttributes());
			}
			else
			{
				vdoc.insertString(vdoc.getLength(),s,asl);
				
				
			}
			
			end=e0.getEndOffset();

		}
		
		vdoc.insertString(vdoc.getLength(), "\n", as);
		
		recePanel.setCaretPosition(vdoc.getLength());		
	}
	
	
}
UI:MainUI.java
package ht.ui;
//主窗口
import ht.bean.Account;
import ht.cmd.Cmd;
import ht.db.DBOper;
import ht_.Send;
import ht_.SendMsg;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Vector;

import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
//启动线程 进入循环等到接收消息
public class MainUI extends JFrame implements MouseListener,ActionListener{

	private Account account,friendAccount;
	private JTabbedPane tab;
	private JLabel lblhead;//登陆后显示的个人资料
	private JList lstFriend;
	private JList lstFamily;
	private JList lstclassmate;
	private JList lsthmd;
	private JButton btnFind;//查找好友按钮
	private Vector<Account> vFriend,vFamily,vClassmate,vHmd,vAllDetail;
	private JPopupMenu pop;//弹出菜单
	private JMenu menu;
	private JMenuItem miChat,miLookInfo,miFriend,miFamily,miMate,miHmd,miDel;//聊天 查看资料 删除好友 移动好友
	//创建哈希表保存所有在线用户的窗口
	private LinkedHashMap<Integer,ChatUI> ht_ChatUsers;
	
	
	public MainUI()
	{
		
		
	}
	public MainUI(Account acc)
	{
		this.account=acc;
		
		setTitle(acc.getNickName());//设置窗口标签栏标题和头像
		setIconImage(new ImageIcon(acc.getFace()).getImage());
		//获取昵称 备注 QQ号 个性签名
		String str="";
		//备注不为空时,显示备注不显示昵称
		if(acc.getRemark()!=null || !acc.getRemark().equals(""))
		{
			str=acc.getRemark()+"(";
		}
		//备注为空时,显示昵称
		else {
			str=acc.getNickName()+"(";
		}
		str+=acc.getQqCode()+")"+acc.getSelfsign();	
		lblhead=new JLabel(str,new ImageIcon(acc.getFace()),JLabel.LEFT);
		add(lblhead,BorderLayout.NORTH);
		
		vFriend=new Vector<Account>();
		vFamily=new Vector<Account>();
		vClassmate=new Vector<Account>();
		vHmd=new Vector<Account>();
		vAllDetail=new Vector<Account>();
		
		
		
		
		
		lstFamily=new JList();
		lstFriend=new JList();
		lstclassmate=new JList();
		lsthmd=new JList();
		
		lstFriend.addMouseListener(this);
		lstFamily.addMouseListener(this);
		lstclassmate.addMouseListener(this);
		lsthmd.addMouseListener(this);
		
		
		
		refresh();//读好友列表
		
		tab=new JTabbedPane();
		tab.add("好友",new JScrollPane(lstFriend));
		tab.add("家人",new JScrollPane(lstFamily));
		tab.add("同学",new JScrollPane(lstclassmate));
		tab.add("黑名单",new JScrollPane(lsthmd));
		add(tab);
		createMenu();
		btnFind=new JButton("查找好友");
		add(btnFind,BorderLayout.SOUTH);

		btnFind.addActionListener(this);
		setSize(300,680);
		setVisible(true);
		setResizable(true);
		//得到屏幕宽度,设置窗口位置
		int width=Toolkit.getDefaultToolkit().getScreenSize().width-300;
		setLocation(width,50);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		//启动消息接收线程
		new ReceThread().start();
		
		
		
	}
	
	
	class listmodel extends AbstractListModel
	{
		Vector dats;
		public listmodel(Vector dats)
		{
			this.dats=dats;
		}
		//获取行数
		public Object getElementAt(int index)
		{
			Account user=(Account) dats.get(index);
			return user.getNickName().trim()+"【"+user.getQqCode()+"】";
		}
		//获取长度
		public int getSize()
		{
			return dats.size();
		}
		
		
	}
	
	//获取好友头像
	class myfind extends DefaultListCellRenderer
	{
		Vector datas;
		public myfind(Vector datas)
		{
			this.datas=datas;
		}
		
		public Component getListCellRendererComponent(JList list,Object value, int index, boolean isSelected,boolean cellHasFocus)
		{
			Component c=super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
			
			if(index >=0 && index<datas.size())
			{
			
			Account user=(Account) datas.get(index);
			//根据列表中的好友在线状态设置头像
			if(user.getStatus()==1)
			{
				setIcon(new ImageIcon(user.getFace()));
			}
			else
			{
				setIcon(new ImageIcon("face/bzx.jpg"));
				
				
			}
			setText(user.getNickName().trim()+"("+user.getQqCode()+")");
			
			}
			
			
			//设置字体颜色
			if(isSelected)
			{
				setBackground(list.getSelectionBackground());
				setForeground(list.getSelectionForeground());
			}
			else
			{
				setBackground(list.getBackground());
				setForeground(list.getForeground());
				
			}
			
			setEnabled(list.isEnabled());
			setFont(list.getFont());
			setOpaque(true);
			return this;
			
			
			
		}
		
		
	}
	
	//创建菜单
	public void createMenu()
	{
		pop=new JPopupMenu();
		miChat=new JMenuItem("聊天");
		miLookInfo=new JMenuItem("查看资料");
		miFriend=new JMenuItem("移动到好友");
		miFamily=new JMenuItem("移动到家人");
		miMate=new JMenuItem("移动到同学");
		miHmd=new JMenuItem("移动到黑名单");
		miDel=new JMenuItem("删除好友");
		
		miChat.addActionListener(this);
		miLookInfo.addActionListener(this);
		miFriend.addActionListener(this);
		miFamily.addActionListener(this);
		miMate.addActionListener(this);
		miHmd.addActionListener(this);
		miDel.addActionListener(this);
		
		pop.add(miChat);
		pop.add(miLookInfo);
		pop.add(miFriend);
		pop.add(miFamily);
		pop.add(miMate);
		pop.add(miHmd);
		pop.add(miDel);
		
		
	}
	
	
	
	//刷新界面
	public void refresh()
	{
		vAllDetail=new DBOper().getAllInfo(account);
		//清楚之前所有的记录
		vFriend.clear();
		vFamily.clear();
		vClassmate.clear();
		vHmd.clear();
		//把数据库的最新数据分别放到对应的向量
		for(int i=0;i<vAllDetail.size();i++)
		{
			Account a=vAllDetail.get(i);
			if(a.getGroupname().equals(Cmd.F_FRIEND))
			{
				vFriend.add(a);
			}
			else if(a.getGroupname().equals(Cmd.F_FAMILY))
			{
				vFamily.add(a);
			}
			else if(a.getGroupname().equals(Cmd.F_CLASSMATE))
			{
				vClassmate.add(a);
			}
			else if(a.getGroupname().equals(Cmd.F_HMD))
			{
				vHmd.add(a);
			}
			
		}
		
		//把向量放入List控件
		lstFriend.setModel(new listmodel(vFriend));//显示资料
		lstFriend.setCellRenderer(new myfind(vFriend));//显示头像
		lstFamily.setModel(new listmodel(vFamily));//显示资料
		lstFamily.setCellRenderer(new myfind(vFamily));//显示头像
		lstclassmate.setModel(new listmodel(vClassmate));//显示资料
		lstclassmate.setCellRenderer(new myfind(vClassmate));//显示头像
		lsthmd.setModel(new listmodel(vHmd));//显示资料
		lsthmd.setCellRenderer(new myfind(vHmd));//显示头像
	}
	@Override
	public void mouseClicked(MouseEvent e) {
		if(e.getSource()==lstFriend)
		{
			friendAccount=(Account)vFriend.get(lstFriend.getSelectedIndex());
			//双击
			if(e.getClickCount()==2)
			{
			//	new ChatUI(account,friendAccount);
				findWin(friendAccount.getQqCode(),null);
				
			}
			//邮件
			if(e.getButton()==3)
			{
	
				//好友被选中
				if(lstFriend.getSelectedIndex()>=0)
				{
					pop.show(lstFriend, e.getX(), e.getY());
				}
				
				
			}
		}
		else if(e.getSource()==lstFamily)
		{
			friendAccount=(Account)vFamily.get(lstFamily.getSelectedIndex());
			//双击
			if(e.getClickCount()==2)
			{

				//new ChatUI(account,friendAccount);
				findWin(friendAccount.getQqCode(),null);
			}
			//邮件
			if(e.getButton()==3)
			{
	
				//被选中
				if(lstFamily.getSelectedIndex()>=0)
				{
					pop.show(lstFamily, e.getX(), e.getY());
				}
				
				
			}
		}
		else if(e.getSource()==lstclassmate)
		{
			friendAccount=(Account)vClassmate.get(lstclassmate.getSelectedIndex());
			//双击
			if(e.getClickCount()==2)
			{

			//	new ChatUI(account,friendAccount);
				findWin(friendAccount.getQqCode(),null);
			}
			//邮件
			if(e.getButton()==3)
			{
	
				//被选中
				if(lstclassmate.getSelectedIndex()>=0)
				{
					pop.show(lstclassmate, e.getX(), e.getY());
				}
				
				
			}
		}
		else if(e.getSource()==lsthmd)
		{
			friendAccount=(Account)vHmd.get(lsthmd.getSelectedIndex());
			//双击
			if(e.getClickCount()==2)
			{
				//new ChatUI(account,friendAccount);
				findWin(friendAccount.getQqCode(),null);
			}
			//右击
			if(e.getButton()==3)
			{
	
				//被选中
				if(lsthmd.getSelectedIndex()>=0)
				{
					pop.show(lsthmd, e.getX(), e.getY());
				}
				
				
			}
		}
		
	}
	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==btnFind)
		{
			new FindUI(account);
		}
		else if(e.getSource()==miChat)
		{
	//		new ChatUI(account,friendAccount);
			findWin(friendAccount.getQqCode(),null);
		}
		else if(e.getSource()==miLookInfo)
		{
			
			if(friendAccount!=null)			
			new LookUsers(friendAccount);
		}
		else if(e.getSource()==miDel)
		{
			new DBOper().delFriend(account, friendAccount.getQqCode());
			refresh();
		}
		else if(e.getSource()==miFriend)
		{
			new DBOper().moveFriend(account, friendAccount.getQqCode(),Cmd.F_FRIEND);
			refresh();
		}
		else if(e.getSource()==miFamily)
		{
			new DBOper().moveFriend(account, friendAccount.getQqCode(),Cmd.F_FAMILY);
			refresh();
		}
		else if(e.getSource()==miMate)
		{
			new DBOper().moveFriend(account, friendAccount.getQqCode(),Cmd.F_CLASSMATE);
			refresh();
		}
		else if(e.getSource()==miHmd)
		{
			
		}
		
		
		
		
		
		
		
		
		
	}
	
	
	//接收消息的线程
			class ReceThread extends Thread
			{
				
				
				public ReceThread()
				{
					//启动线程时 创建保存窗口的哈希表
					ht_ChatUsers=new LinkedHashMap<Integer,ChatUI>();
				}
				public void run()
				{
					
					try 
					{
						
						//自己端口接收数据
						DatagramSocket serverSocket=new DatagramSocket(account.getPort());//在自己端口接收数据
						
						//接收客户端发来的信息存入pack包
						while(true)
						{
							
						byte b[]=new byte[1024*70];	
						DatagramPacket pack=new DatagramPacket(b,b.length) ;//数据包
						serverSocket.receive(pack);
						
						//把字节数组转换成SendMsg对象
						//pack.getLength()接收到的字节数
						ByteArrayInputStream bis=new ByteArrayInputStream(b,0,pack.getLength());//字节数组输入流
						ObjectInputStream ois=new ObjectInputStream(bis);
						SendMsg msg=(SendMsg)ois.readObject();
						
						
				
						
						switch(msg.Cmd)
						{
							
							case Cmd.CMD_ONLINE://接收上线通知
								refresh();
								break;
							case Cmd.CMD_OFFLINE://接收离线通知
								refresh();
								break;
							case Cmd.CMD_CHAT://接收聊天信息
								
								ChatUI chat=findWin(msg.selfAccount.getQqCode(),msg);//显示窗口
								//获取聊天消息
								chat.appendView(msg.selfAccount.getNickName(),msg.doc);
								
								break;
							case Cmd.CMD_DOUDONG://接收抖动信息
								chat=findWin(msg.selfAccount.getQqCode(),msg);//显示窗口
								chat.shake();
							break;
								
							case Cmd.CMD_ADDFRIEND://添加好友
								String str=msg.selfAccount.getNickName()+"添加你为好友 ,请确认";
							
								SendMsg m=new SendMsg();
								m.friendAccount=msg.selfAccount;
								m.selfAccount=msg.friendAccount;
								
								
								System.out.println("aaaaa");
								//如果点击确定按钮就添加
								if(JOptionPane.showConfirmDialog(null,str,"添加好友",JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION)
								{//往朋友表中添加记录
									
									new DBOper().addFriend(msg.friendAccount, msg.selfAccount.getQqCode());
									
									refresh();
									m.Cmd=Cmd.CMD_AFREEFRIEND;
								}else
								{
									m.Cmd=Cmd.CMD_REJECTFRIEND;
								}
								
							break;
								
						
							case Cmd.CMD_AFREEFRIEND://同意
								refresh();//刷新界面
								break;
							
							case Cmd.CMD_REJECTFRIEND://拒绝
								JOptionPane.showMessageDialog(null,msg.selfAccount.getNickName()+"拒接了你的好友请求");
								break;	
							
							
							case Cmd.CMD_FILESEND://接受文件
								String str1=msg.selfAccount.getNickName()+"发送了文件"+msg.sFileName;
								
								int cmd=Cmd.CMD_FILESUCC;
								if(JOptionPane.showConfirmDialog(null,str1,"接收文件",JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION)
								{
									FileDialog dlg=new FileDialog(MainUI.this,"保存",FileDialog.SAVE);
									dlg.setFile(msg.sFileName);
									dlg.show();
									String sfilename=dlg.getDirectory()+"\\"+dlg.getFile();
									File file=new File(sfilename);
									if(!file.exists())
									{
										file.createNewFile();
										
									}
									FileOutputStream fos=new FileOutputStream(sfilename);
									fos.write(msg.b);
									fos.close();
									
								}else
								{
									cmd=Cmd.CMD_FILEFAILED;
									
									
									
								}
								SendMsg msg1=new SendMsg();
								msg1.selfAccount=msg.friendAccount;
								msg1.friendAccount=msg.selfAccount;
								msg1.Cmd=cmd;
								new Send().send(msg1);
								
								break;
								
							case Cmd.CMD_FILESUCC://回复接受成功
								JOptionPane.showMessageDialog(null,msg.selfAccount.getNickName()+"接受了文件");
								break;
								
							case Cmd.CMD_FILEFAILED://回复拒接
								
								JOptionPane.showMessageDialog(null,msg.selfAccount.getNickName()+"拒绝了文件");
								break;	
								
								
								
						}
						
						}
						
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}			
					
					
				}
				
			}
		
	//查找窗口是否存在,如果不存在则创建,存在则直接显示信息在界面
			public ChatUI findWin(Integer qqcode,SendMsg msg)
			{
				ChatUI chat=null;
				//查找窗口是否存在
				chat =ht_ChatUsers.get(qqcode);
				if(chat==null)//不存在则创建聊天窗口
				{
					if(msg==null)//双击或者右键打开窗口
					{
						chat=new ChatUI(account,friendAccount);
					}else//线程打开窗口
					{
						chat=new ChatUI(msg.friendAccount,msg.selfAccount);
					}
					
					//窗口加入哈希表
					ht_ChatUsers.put(qqcode,chat);										
				}
								
				if(!chat.isVisible())
				{
					chat.show();
				}
				return chat;				
			}
			
	//修改用户状态
	public void UpdateStatus(Account acc)
	{
		int size=vAllDetail.size();
		for(int i=0;i<size;i++)
		{
			Account a=vAllDetail.get(i);
			if(a.getQqCode()==acc.getQqCode())
			{
				a.setStatus(acc.getStatus());
				vAllDetail.set(i, a);
				break;
			}
			
			
		}
		refresh();
		
		
	}
	
			
			
			
			
}

操作演示

登录:



注册:


主界面:


查找好友:


右键菜单:


聊天框:




欢迎大家批评指正~~~





  • 23
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值