Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??

一、登陆界面的实现
登陆界面主要使用了JFrame,以及相关的一些组件,并且在界面中加上监听
登陆界面效果图
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

登陆界面代码Login类

package com.lding.login; import com.lding.ui.MsgUI; import javax.swing.*; import java.awt.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.DelayQueue; /** * @program: Net * @description: 登陆类 * @author: 王丁 * @date: 2021-09-25 14:47 **/ public class Login {private OutputStream outputStream; private String port; private InputStream inputStream; private boolean flag=false; private JTextField jTextField; private JPasswordField jPasswordField; public JTextField getjTextField() {return jTextField; }public void setjTextField(JTextField jTextField) {this.jTextField = jTextField; }public JPasswordField getjPasswordField() {return jPasswordField; }public void setjPasswordField(JPasswordField jPasswordField) {this.jPasswordField = jPasswordField; }public boolean isFlag() {return flag; }public void setFlag(boolean flag) {this.flag = flag; }public Login(String port){this.port=port; } public Login(InputStream inputStream,OutputStream outputStream, String port) {this.outputStream = outputStream; this.port = port; this.inputStream=inputStream; }public OutputStream getOutputStream() {return outputStream; }public void setOutputStream(OutputStream outputStream) {this.outputStream = outputStream; }public String getPort() {return port; }public void setPort(String port) {this.port = port; }public InputStream getInputStream() {return inputStream; }public void setInputStream(InputStream inputStream) {this.inputStream = inputStream; }public void showUI(Login login){JFrame jf=new JFrame(); jf.setTitle("??DDqq登陆界面??"); jf.setSize(500,400); //只对顶级容器有效 jf.setDefaultCloseOperation(3); //窗体关闭时结束程序 jf.setLocationRelativeTo(null); //居中 jf.setResizable(false); //选择布局类型,定义流式布局对对象,并且设置每个组件之间相隔5 FlowLayout fl=new FlowLayout(FlowLayout.CENTER,5,5); jf.setLayout(fl); //设置顶级容器的布局为流式布局 //设置不同组件的格式大小 Dimension dim1=new Dimension(500,200); //图片大小 Dimension dim2=new Dimension(100,50); //标签大小 Dimension dim3=new Dimension(300,30); //输入框大小 Dimension dim4=new Dimension(100,40); //按钮大小 //添加组件 //添加图片,先把图片加载到内存中,利用ImageIcon类把图片加载到内存 ImageIcon icon=new ImageIcon("source/Login1.jpg"); JLabel labimg=new JLabel(icon); //不可以直接把图片加到顶级容器中,需要先将其设置为表桥 labimg.setPreferredSize(dim1); jf.add(labimg); //再将标签加到顶级容器中//添加账号标签 JLabel labuser=new JLabel(); labuser.setText("user:"); labuser.setPreferredSize(dim2); jf.add(labuser); //添加账号输入框 JTextField textuser=new JTextField(); textuser.setPreferredSize(dim3); jf.add(textuser); //添加密码标签 JLabel labpassword=new JLabel(); labpassword.setText("password:"); labpassword.setPreferredSize(dim2); jf.add(labpassword); //添加密码输入框 JPasswordField textPassword=new JPasswordField(); textPassword.setPreferredSize(dim3); jf.add(textPassword); //添加一个button按钮 JButton button=new JButton(); button.setBorder(BorderFactory.createRaisedBevelBorder()); button.setText("login"); button.setPreferredSize(dim4); jf.add(button); jf.setVisible(true); //首先实例化登陆按钮监听类的对象,并把登陆界面中的账号和密码输入框的对象传给它 LoginListener ll=new LoginListener(jf,textuser,textPassword,login); //对当前窗体添加监听方法 button.addActionListener(ll); //监控按钮 while (true){//for(int i=0; i<10000000; i++){//for(int j=0; j<1000000; j++){// //} //} //起到延时的作用, System.out.println(1); //如果登陆完毕咋可以跳出这个循环 this.flag=ll.isFlag(); if(this.flag) break; } this.jTextField=ll.getjTextField(); this.jPasswordField=ll.getjPasswordField(); System.out.println("ok"); } }

【Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??】login的监听类 LoginListener
package com.lding.login; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; /** * @program: Net * @description: * @author: 王丁 * @date: 2021-09-25 16:17 **/ public class LoginListener implements ActionListener {private JTextField jTextField; private JPasswordField jPasswordField; private JFrame login; private Login loginnew; private boolean flag=false; public JTextField getjTextField() {return jTextField; }public void setjTextField(JTextField jTextField) {this.jTextField = jTextField; }public JPasswordField getjPasswordField() {return jPasswordField; }public void setjPasswordField(JPasswordField jPasswordField) {this.jPasswordField = jPasswordField; }public boolean isFlag() {return flag; }public void setFlag(boolean flag) {this.flag = flag; }public LoginListener(JFrame login, JTextField jTextField, JPasswordField jPasswordField, Login loginnew) {this.jTextField = jTextField; this.jPasswordField = jPasswordField; this.login = login; this.loginnew=loginnew; }@Override public void actionPerformed(ActionEvent e) {//输入框需要getText()才能得到字符串 if(jTextField.getText().equals("lding")&&String.valueOf(jPasswordField.getPassword()).equals("123456")){this.flag=true; //关闭这个登陆页面,登陆完毕 login.dispose(); }else if(jTextField.getText().equals("Alice")&&String.valueOf(jPasswordField.getPassword()).equals("123456")){System.out.println(2); this.flag=true; login.dispose(); }} }

在登陆完毕后,需要跳转到聊天界面,这里采用的方法是通过一个flag标志来判断是否登陆完毕,当登陆完毕后,会创建新的聊天界面,并且登陆页面会被关闭
依然是双端通信,假定一端为客户端,一端为服务端,其实两端都可为用户。
聊天界面运行图
先登陆Alice的账号 密码为123456
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

登陆成功后显示ok,并等待连接
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

再登陆冷丁的账号,密码为123456
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

当lding账号登陆成功后完成连接,这时候会弹出两个新的JFram窗口,为聊天见面
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

随后可以发送消息,消息可以实时显示时间,并显示用户名
一方发送的消息会在另一方的窗口上实时显示出来
Java后端学习精华|??Java实现模拟QQ(消息通信+登陆界面美化)??
文章图片

MsgClient类代码
package com.lding.net; import com.lding.login.Login; import com.lding.ui.MsgUI; import javax.swing.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; /** * @program: Net * @description: 聊天室客户端 * @author: 王丁 * @date: 2021-09-25 10:42 **/ public class MsgClient {static public JTextField jTextField; staticprivate JPasswordField jPasswordField; public JTextField getjTextField() {return jTextField; }public void setjTextField(JTextField jTextField) {this.jTextField = jTextField; }public JPasswordField getjPasswordField() {return jPasswordField; }public void setjPasswordField(JPasswordField jPasswordField) {this.jPasswordField = jPasswordField; }public staticvoid main(String[] args) throws IOException {//调用登陆界面 String port="客户端"; Login login=new Login(port); login.showUI(login); //为了防止客户端还没登陆就弹出聊天界面 //通过判断flag,当客户端完成登陆后 //在login的监听器中将其flag变为true,从而一层层的把客户端中的flag变为true if(login.isFlag()){//客户端读取登陆用户的名字,也是通过一层层读取 jTextField=login.getjTextField(); String name=jTextField.getText(); System.out.println(login.isFlag()); //创建一个Socket连接 Socket socket=new Socket("127.0.0.1",8888); //输入 输出流对象 InputStream inputStream=socket.getInputStream(); OutputStream outputStream=socket.getOutputStream(); //创建聊天页面 MsgUI msgUI=new MsgUI(outputStream,name); JTextPane showmsgpane=msgUI.initUI(name); //这里用count来判断是用户名输入还是内容输入 //由于消息是两部分拼接的,在消息监听器中先后发送了两部分消息 //第一部分是发送者的名字,第二部分是消息内容 //在输出两种消息的时候采用两种不同的格式,所以对count进行判断 int count=1; while(true){int msglenth=inputStream.read(); System.out.println("消息长度:"+msglenth); byte[] msgbytes=new byte[msglenth]; //将接下来的数据读入字节数组中 inputStream.read(msgbytes); count++; if(count%2==0){SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式 String date = df.format(new Date()); // new Date()为获取当前系统时间,也可使用当前时间戳 String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+date+"["+getmsg+"]"+"说:"+"\n"); }else{String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+getmsg+"\n"); } } } } }

MsgServer代码
package com.lding.net; import com.lding.login.Login; import com.lding.ui.MsgUI; import javax.swing.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; /** * @program: Net * @description: 聊天室服务端 * @author: 王丁 * @date: 2021-09-25 10:42 **/ public class MsgServer {staticpublic JTextField jTextField; staticprivate JPasswordField jPasswordField; public JTextField getjTextField() {return jTextField; }public void setjTextField(JTextField jTextField) {this.jTextField = jTextField; }public JPasswordField getjPasswordField() {return jPasswordField; }public void setjPasswordField(JPasswordField jPasswordField) {this.jPasswordField = jPasswordField; }public void MsgServerInit(){} publicstatic void main(String[] args) throws IOException {//调用登陆页面 String port="服务端"; Login login=new Login(port); login.showUI(login); /*********************************************/ ServerSocket serverSocket=new ServerSocket(8888); System.out.println("等待连接!!"); Socket clientsocket=serverSocket.accept(); //监听连接 System.out.println("连接成功!!"); jTextField=login.getjTextField(); String name=jTextField.getText(); InputStream inputStream=clientsocket.getInputStream(); OutputStream outputStream=clientsocket.getOutputStream(); MsgUI msgUI=new MsgUI(outputStream,name); JTextPane showmsgpane=msgUI.initUI(name); //这里用num来判断是用户名输入还是内容输入 //由于消息是两部分拼接的,在消息监听器中先后发送了两部分消息 //第一部分是发送者的名字,第二部分是消息内容 //在输出两种消息的时候采用两种不同的格式,所以对count进行判断 int num=1; while(true){//根据传入的字符数构造字节数组对象 int msglenth=inputStream.read(); System.out.println("消息长度是:"+msglenth); byte[] msgbytes=new byte[msglenth]; //将接下来的数据读入字节数组中 inputStream.read(msgbytes); num++; if(num%2==0){SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式 String date = df.format(new Date()); // new Date()为获取当前系统时间,也可使用当前时间戳 String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+date+"["+getmsg+"]"+"说:"+"\n"); }else{String getmsg=new String(msgbytes); String msg=showmsgpane.getText(); showmsgpane.setText(msg+getmsg+"\n"); } } } }

代码改进了一下,还有UI的代码再下发 ??Java实现模拟QQ(改进版)?? 之后会丰富更多功能 敬请期待!
感谢您的观看!!!

    推荐阅读