大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
仿QQ聊天室项目
完整代码见
https://github.com/skyerhxx/QQ-Project
完整项目结构
QQ_Client
QQ_Server
二者之间的连接简图
一些界面的程序的对应关系
QqClientLogin
QqFriendList
QqChat
MyServerFrame
开发过程
登录界面
创建普通Java项目
并创建model、view、tools、common 四个包
在view下创建QqClientLogin.java
/** * 功能: qq客户端登录界面 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqClientLogin extends JFrame { //定义界面上部需要的组件 JLabel jbl1; //定义界面中部需要的组件 //定义界面下部需要的组件 JPanel jp1; JButton jp1_jb1,jp1_jb2,jp1_jb3; public static void main(String[] args){ QqClientLogin qqClientLogin = new QqClientLogin(); } public QqClientLogin(){ //处理界面上部 jbl1 = new JLabel(new ImageIcon("./src/resources/tou.gif")); this.add(jbl1,"North"); this.setSize(350,240); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); //设置让它可见 } }
/** * 功能: qq客户端登录界面 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqClientLogin extends JFrame { //定义界面上部需要的组件 JLabel jbl1; //定义界面中部需要的组件 //定义界面下部需要的组件 JPanel jp1; JButton jp1_jb1,jp1_jb2,jp1_jb3; public static void main(String[] args){ QqClientLogin qqClientLogin = new QqClientLogin(); } public QqClientLogin(){ //处理界面上部 jbl1 = new JLabel(new ImageIcon("./src/resources/tou.gif")); //处理界面下部 jp1 = new JPanel(); jp1_jb1 = new JButton(new ImageIcon("./src/resources/denglu.gif")); jp1_jb2 = new JButton(new ImageIcon("./src/resources/quxiao.gif")); jp1_jb3 = new JButton(new ImageIcon("./src/resources/xiangdao.gif")); //把3个按钮放入到jp1 jp1.add(jp1_jb1); jp1.add(jp1_jb2); jp1.add(jp1_jb3); this.add(jbl1,"North"); //把jp1放在页面下部 this.add(jp1,"South"); this.setSize(350,240); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); //设置让它可见 } }
/** * 功能: qq客户端登录界面 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqClientLogin extends JFrame { //定义界面上部需要的组件 JLabel jbl1; //定义界面中部需要的组件 //中部有3个JPanel, 由一个选项卡窗口管理 JTabbedPane jtp; JPanel jp2,jp3,jp4; JLabel jp2_jbl1,jp2_jbl2,jp2_jbl3,jp2_jbl4; JButton jp2_jb1; JTextField jp2_jtf; JPasswordField jp2_jpf; JCheckBox jp2_jcb1,jp2_jcb2; //定义界面下部需要的组件 JPanel jp1; JButton jp1_jb1,jp1_jb2,jp1_jb3; public static void main(String[] args){ QqClientLogin qqClientLogin = new QqClientLogin(); } public QqClientLogin(){ //处理界面上部 jbl1 = new JLabel(new ImageIcon("./src/resources/tou.gif")); //处理界面中部 jp2 = new JPanel(new GridLayout(3,3)); jp2_jbl1 = new JLabel("QQ号码",JLabel.CENTER); jp2_jbl2 = new JLabel("QQ密码",JLabel.CENTER); jp2_jbl3 = new JLabel("忘记密码",JLabel.CENTER); jp2_jbl3.setForeground(Color.blue); jp2_jbl4 = new JLabel("申请密码保护",JLabel.CENTER); jp2_jb1 = new JButton(new ImageIcon("./src/resources/clear.gif")); jp2_jtf = new JTextField(); jp2_jpf = new JPasswordField(); jp2_jcb1 = new JCheckBox("隐身登录"); jp2_jcb2 = new JCheckBox("记住密码"); //把控件按照顺序加入到jp2 jp2.add(jp2_jbl1); jp2.add(jp2_jtf); jp2.add(jp2_jb1); jp2.add(jp2_jbl2); jp2.add(jp2_jpf); jp2.add(jp2_jbl3); jp2.add(jp2_jcb1); jp2.add(jp2_jcb2); jp2.add(jp2_jbl4); //创建选项卡窗口 jtp = new JTabbedPane(); jtp.add("QQ号码",jp2); jp3 = new JPanel(); jtp.add("手机号码",jp3); jp4 = new JPanel(); jtp.add("电子邮件",jp4); //处理界面下部 jp1 = new JPanel(); jp1_jb1 = new JButton(new ImageIcon("./src/resources/denglu.gif")); jp1_jb2 = new JButton(new ImageIcon("./src/resources/quxiao.gif")); jp1_jb3 = new JButton(new ImageIcon("./src/resources/xiangdao.gif")); //把3个按钮放入到jp1 jp1.add(jp1_jb1); jp1.add(jp1_jb2); jp1.add(jp1_jb3); this.add(jbl1,"North"); this.add(jtp,"Center"); //把jp1放在页面下部 this.add(jp1,"South"); this.setSize(350,240); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); //设置让它可见 } }
好友列表界面
新建QqFriendList.java
/* 我的好友列表,也包括陌生人和黑名单 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqFriendList extends JFrame{ //处理第一张卡片 JPanel jphy1,jphy2,jphy3; JButton jphy_jb1,jphy_jb2,jphy_jb3; JScrollPane jsp1; public static void main(String[] args) { QqFriendList qqFriendList = new QqFriendList(); } public QqFriendList(){ //处理第一张卡片 jphy_jb1 = new JButton("我的好友"); jphy_jb2 = new JButton("陌生人"); jphy_jb3 = new JButton("黑名单"); jphy1 = new JPanel(new BorderLayout()); //假定有50个好友 jphy2 = new JPanel(new GridLayout(50,1,4,4)); //给jphy2初始化50个好友 JLabel []jbls = new JLabel[50]; for (int i = 0; i < jbls.length; i++) { jbls[i] = new JLabel(i+1+"", new ImageIcon("./src/resources/mm.jpg"),JLabel.LEFT); jphy2.add(jbls[i]); } jphy3 = new JPanel(new GridLayout(2,1)); //把两个按钮加入到jphy3 jphy3.add(jphy_jb2); jphy3.add(jphy_jb3); jsp1 = new JScrollPane(jphy2); //对jphy1初始化 jphy1.add(jphy_jb1,"North"); jphy1.add(jsp1,"Center"); jphy1.add(jphy3,"South"); this.add(jphy1,"Center"); this.setSize(140,400); this.setVisible(true); } }
/* 我的好友列表,也包括陌生人和黑名单 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqFriendList extends JFrame implements ActionListener,MouseListener{ //处理第一张卡片(好友) //hy = 好友 JPanel jpmsr1,jpmsr2,jpmsr3; JButton jpmsr_jb1,jpmsr_jb2,jpmsr_jb3; JScrollPane jsp2; //处理第二张卡片(陌生人) //msr = 陌生人 JPanel jphy1,jphy2,jphy3; JButton jphy_jb1,jphy_jb2,jphy_jb3; JScrollPane jsp1; //把整个JFrame设置成CardLayout布局 CardLayout cl; public static void main(String[] args) { QqFriendList qqFriendList = new QqFriendList(); } public QqFriendList(){ //处理第一张卡片(显示好友列表) jphy_jb1 = new JButton("我的好友"); jphy_jb2 = new JButton("陌生人"); jphy_jb2.addActionListener(this); jphy_jb3 = new JButton("黑名单"); jphy1 = new JPanel(new BorderLayout()); //假定有50个好友 jphy2 = new JPanel(new GridLayout(50,1,4,4)); //给jphy2初始化50个好友 JLabel []jbls = new JLabel[50]; for (int i = 0; i < jbls.length; i++) { jbls[i] = new JLabel(i+1+"", new ImageIcon("./src/resources/mm.jpg"),JLabel.LEFT); jbls[i].addMouseListener(this); jphy2.add(jbls[i]); } jphy3 = new JPanel(new GridLayout(2,1)); //把两个按钮加入到jphy3 jphy3.add(jphy_jb2); jphy3.add(jphy_jb3); jsp1 = new JScrollPane(jphy2); //对jphy1初始化 jphy1.add(jphy_jb1,"North"); jphy1.add(jsp1,"Center"); jphy1.add(jphy3,"South"); //处理第二张卡片 jpmsr_jb1 = new JButton("我的好友"); jpmsr_jb1.addActionListener(this); jpmsr_jb2 = new JButton("陌生人"); jpmsr_jb3 = new JButton("黑名单"); jpmsr1 = new JPanel(new BorderLayout()); //假定有20个陌生人 jpmsr2 = new JPanel(new GridLayout(20,1,4,4)); //给jphy2初始化50个陌生人 JLabel []jbls2 = new JLabel[20]; for (int i = 0; i < jbls2.length; i++) { jbls2[i] = new JLabel(i+1+"", new ImageIcon("./src/resources/mm.jpg"),JLabel.LEFT); jpmsr2.add(jbls2[i]); } jpmsr3 = new JPanel(new GridLayout(2,1)); //把两个按钮加入到jpmsr3 jpmsr3.add(jpmsr_jb1); jpmsr3.add(jpmsr_jb2); jsp2 = new JScrollPane(jpmsr2); //对jpmsr1初始化 jpmsr1.add(jpmsr3,"North"); jpmsr1.add(jsp2,"Center"); jpmsr1.add(jpmsr_jb3,"South"); cl = new CardLayout(); this.setLayout(cl); this.add(jphy1,"1"); this.add(jpmsr1,"2"); this.setSize(140,400); this.setVisible(true); } @Override public void actionPerformed(ActionEvent arg0) { //如果用户点击了陌生人按钮,就显示第二张卡片 if(arg0.getSource() == jphy_jb2){ cl.show(this.getContentPane(),"2"); } else if(arg0.getSource()==jpmsr_jb1){ cl.show(this.getContentPane(),"1"); } } @Override public void mouseClicked(MouseEvent arg0) { //响应用户双击的事件,并得到好友的编号 if(arg0.getClickCount() == 2){ //得到该好友的编号 String friendNo = ((JLabel)arg0.getSource()).getText(); System.out.println("你希望和 "+friendNo+" 聊天"); } } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent arg0) { JLabel jl = (JLabel)arg0.getSource(); jl.setForeground(Color.red); } @Override public void mouseExited(MouseEvent arg0) { JLabel jl = (JLabel)arg0.getSource(); jl.setForeground(Color.black); } }
效果是鼠标放上变红,移开又变黑
双击会输出 你希望和谁聊天
聊天界面 对象流
Qqchat()
/* 这是与好友聊天的界面 */ package com.qq.client.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class QqChat extends JFrame { JTextArea jta; JTextField jtf; JButton jb; JPanel jp; public static void main(String[] args) { QqChat qqChat = new QqChat("1"); } public QqChat(String friend){ jta = new JTextArea(); jtf = new JTextField(15); jb = new JButton("发送"); jp = new JPanel(); jp.add(jtf); jp.add(jb); this.add(jta,"Center"); this.add(jp,"South"); this.setTitle("你正在和 "+friend+" 聊天"); this.setIconImage(new ImageIcon("./src/resources/qq.gif").getImage()); this.setSize(300,200); this.setVisible(true); } }
接下来是
由它到它
先写服务器,先不涉及数据库
/* 这是服务器端的控制界面,可以完成启动服务器,关闭服务器 可以管理和监控用户 */ package com.qq.server.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MyServerFrame extends JFrame { JPanel jp1; JButton jb1,jb2; public static void main(String[] args) { MyServerFrame mysf = new MyServerFrame(); } public MyServerFrame(){ jp1 = new JPanel(); jb1 = new JButton("启动服务器"); jb2 = new JButton("关闭服务器"); jp1.add(jb1); jp1.add(jb2); this.add(jp1); this.setSize(500,400); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } }
用对象流获取用户发送的消息
如何在网络间传递对象:对象流
对象流还要将对象序列化,才能在网络上传输
登录验证
MyServerFrame是服务器
先启动QQ_Server中的MyServerFrame
启动QQ_Client中的QqClientLogin
输入正确的密码123456
一对一聊天
多对多的聊天
实现多人聊天
每一个用户登录都会开一个线程. 你有3个用户登录就有3个线程同时在处理这3个用户与服务器的交互
把接收到的消息,显示到该显示的聊天界面(这是第7集的内容)
好友在线提示
好友在线,头像就是彩色的,不在线就是灰色的
当用户一登录成功了之后,迅速发一个请求包,让服务器给返回有哪些人在线
所有在线的人都存在一个HashMap里面,遍历就可找到所有的
现在可以看到在线的好友头像点亮,不在线的头像是灰色
但是后面登录的人可以看到前面登录的人,前面登录的人看不到后面登录的人
下面是第8集
后面登录的人应该有责任去通知其他在线的人他上线了,然后去更改他们的好友在线情况
功能全部实现
至此,项目完结
参考视频:
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/197211.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...