自己动手写一个java版QQ

来源:互联网 发布:linux 机器重启时间 编辑:程序博客网 时间:2024/05/18 01:32
基于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";//连接数据源  数据源名称是LocalServerstatic 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;}@Overridepublic 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);}}@Overridepublic 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 blocke1.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文件传输一次最多64kif(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));//显示头像}@Overridepublic 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());}}}}@Overridepublic void mouseEntered(MouseEvent arg0) {// TODO Auto-generated method stub}@Overridepublic void mouseExited(MouseEvent arg0) {// TODO Auto-generated method stub}@Overridepublic void mousePressed(MouseEvent arg0) {// TODO Auto-generated method stub}@Overridepublic void mouseReleased(MouseEvent arg0) {// TODO Auto-generated method stub}@Overridepublic 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 blocke.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();}}

操作演示

登录:



注册:


主界面:


查找好友:


右键菜单:


聊天框:




欢迎大家批评指正~~~





原创粉丝点击